💎一站式轻松地调用各大LLM模型接口,支持GPT4、智谱、星火、月之暗面及文生图 广告
### [[Prototype]] 当你试图引用对象的时候,就会触发[[Get]]操作,当对象本身不含有该属性时就会查找[[Prototype]]链,如果链没有找到该属性并且链不为空,则会继续顺延[[Prototype]]继续查找下去。 for...in...会枚举出所有可enumerable的属性,包括原型链上的。 而...in...操作符来检查属性时也会查找原型链(无论属性是否可枚举)。 #### 屏蔽 所谓屏蔽,就是原型链上有foo属性,而对象本身没有该属性,当执行obj.foo操作时会为该对象添加foo属性,原型链的foo会被遮蔽。 1. 如果原型链上存在foo属性,且可读,则obj.foo操作会直接在obj上添加foo属性。 2. 如果原型链上存在foo属性,且不可读,则该操作会失败,foo属性不会被添加。 3. 如果原型链上存在foo属性,且设置了setter,则该操作会触发setter。foo不会被添加,也不会重新定义这个setter。 隐示屏蔽 ``` var obj1 = {a: 2}; var obj2 = Object.create(obj1); obj1.a; //2 obj2.a; //2 obj2.hasOwnProperty('a'); //false obj2.a++; obj1.a; //2 obj2.a; //3 obj2.hasOwnProperty('a'); //true //obj2.a++实际上就是obj2.a = obj2.a + 1,创建了一个新的自身的a,屏蔽了原型的 ``` ### 类 new操作符并不是创建新的实例,而是让“新实例”的原型指向函数的prototype。 ``` function Foo() {}; var a = new Foo(); Object.getPrototypeOf(a) === Foo.proptotype; //true ``` #### 构造函数与调用 Foo与其他函数没有任何区别,当使用new调用时会执行“构造函数调用”。 ``` function Foo() {console.log(123)}; var a = new Foo(); //123 console.log(a); //{} ``` 所以,js中的构造函数,其实就是带new的普通函数罢了。 回顾构造函数,.constructor并不是代表“由谁构造”,它只是委托。 ``` //函数自带constructor Foo.prototype.constructor == Foo; //true var a = new Foo(); //a没有constructor,此时会查找原型链,Foo的原型上有constructor,返回 a.constructor === Foo; //true Foo.prototype = {}; var b = new Foo(); //现在,Foo.prototype已经没有了constructor,只能继续向上查找,直到Object(Object.prototype.constructor) b.constructor === Foo; //false b.constructor === Object; //true ``` ### 原型继承 ``` //创建一个新的Bar.prototype对象并指向Foo.prototype,旧的Bar.prototype会被抛弃。修改Bar.prototype不会影响Foo.prototype Bar.prototype = Object.create(Foo.prototype); //直接指向Foo.prototype,修改Bar.prototype会影响Foo.prototype Bar.prototype = Foo.prototype; //另一种实用的方法,es6的api,直接修改现有的Bar.prototype并且不影响Foo.prototype Object.setPrototypeOf(Bar.prototype, Foo.prototype) ``` `var b = Object.create(a)`,如果a是对象的话会创建新的b.prototype并将其指向a,如果a是函数的话则b.prototype将会指向a.prototype。 ``` function A(){this.name = 1}; var b = Object.create(A); //b是一个函数 b.prototype.constructor === A; //true var A = {a: 1}; var b = Object.create(A); b.prototype; //undefined b.__proto__ === A; //true ```