function Fn() { // 代码字符串 // 谁 new 就是谁的私有属性 this.x = 100; this.y = 200; this.getX = function() { console.log(this.x); }; // 每个函数都有 prototype 对象 // 所以 prototype 是一个堆 Fn.prototype // Fn.prototype 对象也带 __proto__ 属性 // 这个对象上有 constructor // constructor 指向函数本身 }; // 把 getX 挂载到 Fn 的原型对象上 // 生成一个新的堆内存 // 属于公共属性 Fn.prototype.getX = function() { console.log(this.x); }; // 把 getY 挂载到 Fn 的原型对象上 // 生成一个新的堆内存 // 属于公共属性 Fn.prototype.getY = function() { console.log(this.y); }; // 括号可加可不不加 // 都是创建类的实例 // 创建实例对象 f1 / f2 (堆) // 同时创建 x: 100 y: 200 getX: function() { ... } // 都是这个实例的私有属性 // 通过 this 创建的变量和对象都属于私有属性 // 实例都带 __proto__ 属性 // __proto__ 所属类的原型 prototype // 通过原型链往上找都属于 实例(Fn.prototype) 的共有属性 let f1 = new Fn(); let f2 = new Fn; // Object内置类(堆) // 有自己的 prototype 原型对象 // prototype 指向 Object.prototype 原型对象 // 有自己的 __proto__ 属性 // 有自己的 constructor 属性 // constructor 指向 Object // Object.prototype 的 __proto__ 指向的是 null // 实例指向的堆内存不同,如果自己私有就不会往原型类上查找 // 因为这个 getX 函数自己私有 // 所以两个实例的 getX 方法不相等 console.log(f1.getX === f2.getX); // false // 因为 getY 这个函数不是自己私有 // 所以往原型链上查找,结果相等 // 原因就是他们的 __proto__ 都指向 Fn.prototype 原型对象 console.log(f1.getY === f2.getY); // true // 通过原型链查找到的是公共的 getY // 类似于 f1.getY === f2.getY console.log(f1.__proto__.getY === Fn.prototype.getY); // true // f1.__proto__.getX 找的是 Fn.prototype 公共属性 // f2.getX 因为自己私有 // 所以不相等 console.log(f1.__proto__.getX === f2.getX); // false // f1.getX 属于自己私有的属性 // Fn.prototype.getX 本身就是公共属性 // 所以不相等 console.log(f1.getX === Fn.prototype.getX); // false // f1 自己身上没有 constructor // 往原型对象上查找 // 又因为 constructor 指向 函数本身 // 所以结果就是 Fn 函数 console.log(f1.constructor); // Fn 函数 // Fn.prototype 的 __proto__ 指向的是 Object.prototy // 因为 Object.prototy 的 constructor 指向 Object 本身 // 所以是结果 Object console.log(Fn.prototype.__proto__.constructor); // ƒ Object() { [native code] } // f1.getX() 执行 // 并且 f1.getX 是属于自己私有 // 所以输出 100 // 函数执行前面有点 f1.getX(); // 100 // f1.__proto__.getX(); // 直接查找的是原型对象上的 getX() // 原型上的是 console.log(this.x); // 因为 f1.__proto__.getX(); getX() 前面有点 // 所以 相当于 f1.__proto__.x // f1.__proto__.x 直接跳过自己(f1 实例对象(堆))往原型对象上查找 // 此时原型对象上也没有,再往 Object.prototype 对象上查找 // Object 对象上也没有 // 最后得到的是 undefined f1.__proto__.getX(); // undefined // 与 f1.getX(); 相同 f2.getY(); // 200 // Fn.prototype.getY(); // 直接查找的是原型对象上的 getY() // 原型上的是 console.log(this.y); // 因为 Fn.prototype.getY(); getY() 前面有点 // 所以 相当于 Fn.prototype.y // Fn.prototype.y 直接跳过自己(f2 实例对象(堆))往原型对象上查找 // 此时原型对象上也没有,再往 Object.prototype 对象上查找 // Object 对象上也没有 // 最后得到的是 undefined Fn.prototype.getY(); // undefined
prototype和__proto__笔试题
关注
打赏