在原型上增加属性或者⽅法有什么益处

如果不通过原型的⽅式,每⽣成⼀个新对象,都会在内存中新开拓⼀块存储空间,当对象变多之后,性能会变得很差。
常见写法

Fun.prototype.xx = function () {};Fun.prototype.xx = function () {};Fun.prototype.xx = function () {};

这种⽅式向原型对象增加属性或者⽅法的话,⼜显得⾮常麻烦。转换形式

Fun.prototype = { start: function () { console.log("start"); }, end: function () { console.log("end"); },};

如何找到Fun的原型对象

function Fun(attr) { this.attr = attr;}Player.prototype.start = function () { console.log(attr + "start");};const f1 = new Fun("1");const f2 = new Fun("2");console.log(f1.__proto__); // Fun {}console.log(Object.getPrototypeOf(f1)); // Fun {},能够通过// Object.getPrototypeOf来获取__proto__console.log(Fun.prototype); // Fun {}console.log(Fun.__proto__); // [Function]

new 关键字到底做了什么

1 ⼀个继承⾃ Fun.prototype 的新对象 f1 被创立
2 f1.proto 指向 Fun.prototype,即 f1.proto = Fun.prototype
3 将 this 指向新创建的对象 f1
4 返回新对象; 如果构造函数没有显式返回值,则返回 this;如果构造函数有显式返回值,是根本类型,⽐如 number,string,boolean, 那么还是返回;如果构造函数有显式返回值,是对象类型,⽐如{ a: 1 }, 则返回这个对象{ a: 1 }.通过打印实例能够验证

依据new关键字所做内容,模仿new的实现

function Fun(name) {  this.name = name;}function objectFactory() {  let o = new Object();  let FunctionConstructor = [].shift.call(arguments);  o.__proto__ = FunctionConstructor.prototype;  let resultObj = FunctionConstructor.apply(o, arguments);  return typeof resultObj === "object" ? resultObj : o;}const f1 = objectFactory(Fun, "a");console.log(f1);

原型链是什么

当读取实例的属性时,如果找不到,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,⼀直找到最顶层为⽌。
简略测试用例,如果f1实例在Fun的原型中找不到,会始终往上找到Object的原型属性.

Object.prototype.x = 'Object_x'function Fun(){}Fun.prototype.x = 'Fun_x'const f1 = new Fun()console.log(f1.x)

这样⼀条通过proto和 prototype 去连贯的对象的链条,就是原型链

业界争议鸡生蛋问题

Object instanceof Function; // trueFunction instanceof Object; // trueObject instanceof Object; // trueFunction instanceof Function; // true

由第一句和第二句推导出

Object.__proto__ === Function.prototypeFunction.__proto__.__proto__ === Object.prototype

推导出

Function.__proto__ === Function.prototype

由此产生一个业界争执, Function 对象是不是由 Function 构造函数创立的一个实例
解释 1、Function 对象是由 Function 构造函数创立:依照 JavaScript 中“实例”的定义,a 是 b 的实例即 a instanceof b 为 true,默认判断条件就是 b.prototype 在 a 的原型链上。而 Function instanceof Function 为 true,实质上即 Object.getPrototypeOf(Function) === Function.prototype,正合乎此定义。

解释 2、Function 对象不是由 Function 构造函数创立:Function 是 built-in 的对象,也就是并不存在“Function对象由Function构造函数创立”这样显然会造成鸡生蛋蛋生鸡的问题。实际上,当你间接写一个函数时(如 function f() {} 或 x => x),也不存在调用 Function 结构器,只有在显式调用 Function 结构器时(如 new Function('x', 'return x') )才有。