js原型、原型链的深入
要理解原型,首先要了解构造函数、原型对象
所有函数在创建的时候,都会产生一个prototype属性,prototype指向的是原型对象,而原型对象中包含了构造函数,构造函数又指向了函数本身
简单的用图表示就是一个三角恋的情况
function Person(){}
let personOne = new Person()
console.log(Person.prototype === personOne.__proto__) // true
console.log(Person === personOne.__proto__.constructor) // true
让我们输出看看原型对象究竟包含了什么
function persons() { }
console.log(persons.prototype)
console.log(persons.prototype.__proto__)
我们可以看到,创建一个空的函数,其原型中包含了两个属性,一个是constructor,一个是__proto__,其中constructor是构造函数,我们可以看到constructor构造函数后跟的是persons,说明构造函数指向的是函数本身,而__proto__我们可以看出其constructor指向的是object(),说明__proto__指向的是原型链中的上一层,而自定义函数的上一层就是顶层是object。
原型的特点
1、在函数的原型对象上添加的属性和方法能够在其所有实例中共享
function Person(){}
Person.prototype.name = '谢小虫虫'
Person.prototype.sayHi = function(){
console.log('hi')
}
let personOne = new Person()
console.log(personOne.name) // 谢小虫虫
let personTwo = new Person()
console.log(personTwo.name) // 谢小虫虫
2、当实例中存在与原型对象中同名的属性或方法时,实例中的属性或方法覆盖原型中的属性或方法
function Person(){}
Person.prototype.name = '谢小虫虫'
Person.prototype.sayHi = function(){
console.log('hi')
}
let personOne = new Person()
personOne.name = '隔壁老王'
console.log(personOne.name) // 隔壁老王
let personTwo = new Person()
console.log(personTwo.name) // 谢小虫虫
3、通过查找原型链的方式获取数据,当查找数据时,首先查找实例本身中有无该数据,如果没有,通过__proto__查找其上一层原型,再没有,再往上找,直到最顶层的Object
更改原型的方式
1、直接更改
Person.prototype.name = '谢小虫虫'
2、通过对象字面量(注意,通过对象字面量的方式等同于创建新对象,这时原本原型对象中的构造函数就不存在了,需要手动指向构造函数)
Person.prototype = {
constructor: Person
name = '谢小虫虫'
sayHi = function(){
console.log('hi')
}
}
补充:
可以使用hasOwnProperty方法判断属性是否存在实例中
可以使用hasPrototypeProperty方法判断属性是否存在原型中