js ——原型、原型链理解

171 阅读2分钟

1.构造函数创建对象

function Person(){}
let person = new Person()
let person1 = new Person()
person.name = 'lisa'
console.log(person.name)
console.log(person1.name)

Person 为构造函数,使用new 创建出来 person 、person1 实例对象

2.函数属性 prototype

每个函数都有prototype属性

函数的prototype属性指向一个对象,是通过构造函数new出来person 和 person1实例的原型

3.对象的__proto__属性

每个对象都有__proto__属性(除了null),该属性指向对象的原型

console.log(person.__proto__ === Person.prototype)

4.constructor 属性

结合第2点和第3点,构造函数的prototype属性 和对象的__proto__ 都指向对象的原型,

那原型是否有属性指向 构造函数 和 实例 呢?

原型的constructor 属性 指向 关联的构造函数; 无属性指向实例(因为构造函数可创建多个实例)

console.log(Person.prototype.constructor === Person)

到此构造函数、实例 、原型三者关系已经了解

5.原型链的理解

每个对象在读取属性时先检查其私有属性,如果存在则返回私有属性,不存在则向person.__proto__原型对象查找。

原型的原型(原型对象就是通过 Object 构造函数生成的),原型链最顶端为null。

github.com/mqyqingfeng…

6.原型继承

对象之间的关联性,如果每个对象都是独立的属性和方法,而且多个对象内属性和方式是公共相同的,那么会严重消耗资源,所以会使用到原型继承

实例1:构造函数继承(指向对应的原型对象)

function An(){}
An.prototype.name = 'lili'
An.prototype.run = function(){
console.log(this.name + 'run')
}
function Bn(){}
Bn.prototype  = An.prototype 
Bn.prototype.constructor = Bn  
//注意:原型指向后,Bn的constructor也指向了An,这时候需要重新指向关联的构造函数
let b = new Bn()
console.log(b.name)

存在的问题:Bn的原型对象修改后会直接反应到An的原型对象

Bn.prototype.name ='lisa'
let a = new An()
console.log(a.name)

调整:Bn的原型对象直接指向An的实例

function An(){}
An.prototype.name = 'lili'
An.prototype.run = function(){
console.log(this.name + 'run')
}
function Bn(){}
Bn.prototype  = new An()
Bn.prototype.constructor = Bn  
//注意:原型指向后,Bn的constructor也指向了An,这时候需要重新指向关联的构造函数
Bn.prototype.name = 'lisa'
let b = new Bn()
let a = new An()
console.log(b.name,a.name)

实例2:对象继承

let old = {name:"old",age:18}
let one = {}
one.__proto__ = old  //指向old,没找到则通过__proto__向上查找
console.log(one.name)
one.__proto__.name = 'new'
console.log(one.name,old.name)

问题:修改one的原型直接影响了old

方案:Object.create()可以通过指定的原型对象创建一个新的对象,新的对象不会影响原型

let old = {name:"old",age:18}
let one = {}
one.__proto__ = Object.create(old)
one.__proto__.name = 'new'
console.log(one.name,old.name)

7.原型的方法

设置原型对象方法

  • obj.__proto__=prototypeObj
  • Object.setPrototypeOf(obj, prototypeObj)
  • Object.create(prototypeObj)

检测原型:使用 isPrototypeOf() 方法可以判断该对象是否为参数对象的原型