原型
[[prototype]] :proto
在 JavaScript 中,每个对象(包括Function)都有一个特殊的隐藏属性 [[Prototype]],它要么为 null,要么就是对另一个对象的引用, 若为其他的类型都会被忽略。该对象被称为“原型”。
从 obj 中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。
1.1 设置/获取原型
proto :
obj.__proto__ = objProto__proto__与内部的[[Prototype]]是不一样的。__proto__是[[Prototype]]的 getter/setter
Object.setProtoTypeOf(obj,objProto)Object.getProtoTypeOf(obj)
注意: 原型仅用于的读取属性, 对于写入/删除操作可以直接在对象上进行。
__proto__ 不是一个对象的属性,只是 Object.prototype 的访问器属性:
因此,如果 obj.__proto__ 被读取或者赋值,那么对应的 getter/setter 会被从它的原型中调用,它会 set/get [[Prototype]]。__proto__** 是一种访问 [[Prototype]] 的方式,而不是 [[prototype]] 本身**。
Object.create(null)
1.2 “this”的指向
this 根本不受原型的影响。
无论在哪里找到方法:在一个对象还是在原型中。在一个方法调用中,this 始终是点符号 . 前面的对象。
这将决定:当继承的对象运行继承的方法时,它们将仅修改自己的状态,而不会修改大对象的状态。
let animal = {sleep() {this.isSleeping = true;}};let rabbit = {name: "White Rabbit",__proto__: animal};// 修改 rabbit.isSleepingrabbit.sleep();alert(rabbit.isSleeping); // truealert(animal.isSleeping); // undefined(原型中没有此属性)
1.3 属性遍历
for ... in: 既遍历自身属性, 也遍历继承属性, 且是可枚举的obj.hasOwnProperty(key): 过滤掉继承的属性
Object.keys(obj): 只包含自身可枚举属性Object.values(obj)Object.enties(obj)
F.prototype
每个函数都有 "prototype" 属性, 且只有函数有**Prototype**属性,它指向这个函数得原型对象。
默认的原型对象只有一个属性 constructor ,指向函数自身。
- 注:在常规对象上,
prototype没什么特别的,仅仅是一个普通的属性。let A = {};let B = function(){};let b = new B();console.log(A.prototype) // undefinedconsole.log(B.prototype) // {constructor: ƒ}console.log(b.__proto__ === B.prototype) // true

使用new F()这样的构造函数来创建一个新对象时,
如果F.prototype是一个对象,那么new操作符会使用它为新对象设置[[Prototype]]。
F.prototype属性仅在new F被调用时使用。 如果在创建之后,F.prototype属性有了变化(F.prototype = <another object>),那么之后通过new F创建的新对象也将随之拥有新的对象作为[[Prototype]],但已经存在的对象将保持旧有的值。
var A = function() {};A.prototype.n = 1;var b = new A();A.prototype = {n: 2,m: 3}var c = new A();console.log(b.n); // 1console.log(b.m); // undefinedconsole.log(c.n); // 2console.log(c.m); // 3
constructor
函数原型对象上有一个 constructor 属性,它指向函数自身。
Rabbit.prototype.constructor == Rabbit```javascript function Rabbit() {} // by default: // Rabbit.prototype = { constructor: Rabbit }
alert( Rabbit.prototype.constructor == Rabbit ); // true
可以使用 `constructor` 属性来创建一个新对象,该对象使用与**现有对象**有相同的**构造器**。- `let inst2 = new inst1.constructor(...args);````javascriptfunction Rabbit(name) {this.name = name;alert(name);}let rabbit = new Rabbit("White Rabbit");let rabbit2 = new rabbit.constructor("Black Rabbit");
原型链
- 每个对象都拥有一个原型对象:
newFoo的原型是Foo.prototype - 对象的原型可能也是继承自其它的原型对象:
Foo.prototype也有它的原型Object.prototype - 一层一层的,以此类推,这种关系就是原型链
每个对象拥有一个原型对象,通过__proto__ 指针指向上一个原型 ,并从中继承方法和属性,同时原型对象也可能拥有原型,这样一层一层,最终指向null,这种关系被称为原型链(prototype chain)。
当试图得到一个对象的某个属性时,如果这个对象本身没有这个属性,那么会去它的__proto__ (即它的构造函数的prototype)中寻找。
一个对象是否在另一个对象的原型链上
1. instanceof
语法:obj instanceof constructor
检测 constructor.prototype是否存在于参数 obj 的原型链上。
let Fn = function () { }let f = new test();f instanceof Fn // truef instanceof Function // falsef instanceof Object // true
2. isPrototypeOf
语法:protoObj.isPrototypeOf(obj)
检测一个对象是否存在于另一个对象的原型链上
let Fn = function () { }let f = new test();Fn.prototype.isPrototypeOf(testObject) // trueObject.prototype.isPrototypeOf(testObject) // true
