Prototypal Inheritance
[[Prototype]] vs __proto__ vs .prototype in Javascript
A simplified overview of JavaScript prototypes and prototypical inheritance.
[[Prototype]]
[[Prototype]]是 Javascript 中所有对象都具有的隐藏私有属性,它保存着对对象原型的引用。[[Prototype]]is a hidden private property that all objects have in Javascript, it holds a reference to the object’s prototype.An object’s prototype is the object that an object inherits or descends from. 对象的原型是对象继承或派生的对象。
In the following diagram the object
sondescends fromfather, sofatheris the prototype ofson. That means the hidden[[Prototype]]property ofsonpoints tofather.
__proto__
__proto__是Object.prototype的一个属性,它公开对象的隐藏[[Prototype]]属性并允许您访问或修改它。您不应该使用它,因为它已被弃用。
function Person(name) {
this.name = name;
}
const p = new Person('Jack');
console.log('__proto__ =', p.__proto__)
console.log('p =', p)

- 访问对象原型的现代方法是使用
Object.getPrototypeOf(obj)。您还可以使用Object.setPrototypeOf(obj, prototype)修改对象的原型。
let father = { name:'aa' };
let son = {};
Object.setPrototypeOf(son, father);
console.log("son's prototype getPrototypeOf =", Object.getPrototypeOf(son));
console.log("son's prototype __proto__ =", son.__proto__);
console.log(Object.getPrototypeOf(son) === son.__proto__); // true

.prototype
.prototype是一个几乎所有函数都具有的特殊属性,仅在将函数作为构造函数调用时使用。说几乎所有是因为使用简洁语法定义的箭头函数和方法没有.prototype属性,不能用作构造函数。.prototypeis a special property that almost all functions have that is only used when a function is invoked as a constructor function. I say almost all because arrow functions and methods defined using the concise syntax do not have.prototypeproperties and cannot be used as constructors..prototype属性包含对对象的引用,当构造函数用于实例化或创建新对象时,.prototype被设置为新对象的原型。当构造函数
ObjectFactory实例化一个对象obj,obj的内部隐藏属性[[Prototype]]和ObjectFactory.prototype指向的是同一个对象(obj’s[[Prototype]]property references the same object asObjectFactory.prototype)。这意味着ObjectFactory.prototype中定义的任何属性或方法都可以被obj访问。
function ObjectFactory() {
this.property = `Hi, I'm a property`;
}
let obj = new ObjectFactory();
console.log(typeof ObjectFactory.prototype); // object
console.log(ObjectFactory.prototype.isPrototypeOf(obj)); // true
console.log(obj.__proto__ === ObjectFactory.prototype); // true
console.log(obj.__proto__ === ObjectFactory.prototype === Object.prototype); // false
console.log(Object.getPrototypeOf(ObjectFactory.prototype) === Object.prototype); // true
console.log(Object.prototype.isPrototypeOf(ObjectFactory.prototype)); // true
ObjectFactory.prototype.prop = `I'm a property of ObjectFactory.prototype`;
console.log(obj.__proto__.prop); // I'm a property of ObjectFactory.prototype
console.log(obj); // ObjectFactory {property: "Hi, I'm a property"}
console.log(obj.prop); // I'm a property of ObjectFactory.prototype
var obj1 = new Object();
var obj2 = {};
var obj3 = { a: 1 };
console.log( Object.getPrototypeOf( obj1 ) === Object.prototype ); // 输出:true
console.log( Object.getPrototypeOf( obj2 ) === Object.prototype ); // 输出:true
console.log( Object.getPrototypeOf( obj3 ) === Object.prototype ); // 输出:true
info
prototype是所有构造函数都具有的属性;[[Prototype]]是所有对象都具有的隐藏私有属性;当构造函数ObjectFactory实例化一个对象obj,obj的内部隐藏属性[[Prototype]]指向obj的原型,即ObjectFactory.prototype。ObjectFactory.prototype的原型,即Object.prototype。也就是说,构造函数.prototype的原型 是Object.prototype。使用构造函数
Object或 字面量{ }创造的对象,其原型是Object.prototype。
Understanding Prototypal Inheritance In JavaScript
要理解原型继承,我们需要理解这三个关键概念,即:继承(inheritance)、原型(prototype)、原型链(prototype chain)
- 继承是指一个对象可以访问另一个对象的属性和方法的过程。
- 一个对象、它的原型和它的原型的原型,一直到最后一个原型之间的对象引用链称为原型链。
const AppleInc = {
name: "Apple",
logo: "Apple fruit",
operating_system: "Apple Software",
on () {
console.log("Turning on your " + this.name + " device")
},
off () {
console.log("Turning off your " + this.name + " device")
}
}
const iPhone = {
name: "iPhone",
operating_system: "ios"
}
console.log(iPhone)
// sets AppleInc to be the prototype of the iPhone object.
iPhone.__proto__ = AppleInc // NEVER DO THIS IN REAL-LIFE. ONLY FOR DEMONSTRATION PURPOSE
console.log(iPhone) // logs iPhone with AppleInc as its prototype.
console.log(iPhone.on()) // Turning on your iPhone device
console.log(iPhone.off()) // Turning off your iPhone device
console.log(iPhone.name)

- 结合
this查看原型链
info
this 首先指向发起调用的对象,因为它可以在 iPhone 对象中找到name property,所以它指向该对象。但它无法在 iPhone 对象中找到store property,因此它指向其原型并在那里查找该属性并找到它。
- All data types in JavaScript have a prototype object, JavaScript 中的根对象是
Object.prototype,Object.prototype的原型对象是null
An Easy Guide To Understanding Constructors In JavaScript
constructors
- 构造函数 实际上是普通的 JavaScript 函数。它们的特别之处在于它们总是与 JavaScript 中一个非常强大的运算符一起调用,称为
new运算符。
function Person () {
this.firstname = "Lawrence"
this.lastname = "Eagles"
this.occupation = "Software Developer"
this.gender = "male"
}
Person(); // 不使用new则就是普通函数调用
console.log('此时this指向全局对象 --->', window.firstname); // 此时this指向全局对象 ---> Lawrence