一、什么是原型和原型链?
首先我们知道JS中对象分为函数对象和普通对象,其中所以对象都有_proto_,但是只有函数对象才具有prototype。
1.原型
①所有引用类型都有一个__proto__(隐式原型)属性,属性值是一个普通的对象,constructor和__proto__,constructor表示对象是由哪个构造函数创建的比如下面的test.constructor ==Test
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype,也就是对象的__proto__保存着该对象的prototype
举例:
var a = [0,1,2];
a.__proto__ === Array.prototype; // true
2.原型链
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
举例:
function People(age, name) {
this.age = age
this.name = name
}
const person1 = new People(24, '流小枫')
console.log(person1.age); //24
console.log(person1.name); //'流小枫'
console.log(person1.height); //undefined
console.log(person1.__proto__ === People.prototype); //true,证实了上面的“对象的__proto__保存着该对象的prototype”
我们为了证实person1.proto === People.prototype,还可以这样(第一次打印):
function People(age, name) {
this.age = age
this.name = name
}
const person1 = new People(24, '流小枫')
console.log(person1.__proto__ === People.prototype, ); //true,对象的__proto__保存着该对象的prototype
console.log(person1.__proto__); //第一次打印
第一次打印结果:
第二次打印:
function People(age, name) {
this.age = age
this.name = name
}
const person1 = new People(24, '流小枫')
console.log(person1.__proto__ === People.prototype, ); //true,对象的__proto__保存着该对象的prototype
People.prototype.height = 180
console.log(person1.__proto__); //第二次打印
第二次打印打印结果:
通过上述例子可以证实person1.proto === People.prototype
在person1中查找某个元素时,会执行下面的步骤:
访问链路为:
我们通过一个例子来解释一下:
function Test() {
this.a = 1
}
const test = new Test()
console.log(test);
Test.prototype.b = 2
console.log(Test.prototype.__proto__ === Object.prototype); //true
console.log(Object.prototype.__proto__); //null,Object没有__proto__
Object.prototype.c = 3 //因为Test.prototype.__proto__ ===Object .prototype
console.log('------------------------------------------');
console.log(test.a);
console.log(test.b);
console.log(test.c);
打印结果:
从这里我们可以看见查找属性是一层一层的查找,这也叫原型继承
①一直往上层查找,直到到null还没有找到,则返回undefined
②Object.prototype.proto === null
③所有从原型或更高级原型中的得到、执行的方法,其中的this在执行时,指向当前这个触发事件执行的对象
3.判断对象是否存在该属性
判断对象本身是否存在该属性(hasOwnProperty())和原型链上是否存在该属性(属性名 in 对象)
function Test() {
this.a = 1
}
const test = new Test()
Test.prototype.b = 2
Object.prototype.c = 3
// hasOwnProperty(),用来判断对象本身是否含有这个属性
console.log(test.hasOwnProperty('a')); //true
console.log(test.hasOwnProperty('b')); //false
console.log(test.hasOwnProperty('c')); //false
console.log('——————————————————————————————————————');
//属性名 in 对象,来判断原型链上是否有这个属性
console.log('a' in test);
console.log('b' in test);
console.log('c' in test);