js中的原型链
- Published on
本文最近一次更新于 492 个天前,其中的内容很可能已经有所发展或是发生改变。
前言
最近被裁员了,不得已重新复习下基础知识。本章巩固下 javascript
中原型链相关的知识,基于高级程序设计以及 mdn 上的文档整理相关知识。
整体图
根据 mdn 上文档,思维导图上的 proto
指向,实际等同于 Object.getPrototypeOf(xxxxxx)
。preson1.__proto__
为非标准写法,在浏览器控制台上实际上能看到的 [[Prototype]]
才是真正的原型,并通过 Object.getPrototypeOf
函数访问。
遵循 ECMAScript 标准,符号
someObject.[[Prototype]]
用于标识someObject
的原型。内部插槽[[Prototype]]
可以通过Object.getPrototypeOf()
和Object.setPrototypeOf()
函数来访问。这个等同于 JavaScript 的非标准但被许多 JavaScript 引擎实现的属性__proto__
访问器。为在保持简洁的同时避免混淆,在我们的符号中会避免使用obj.__proto__
,而是使用obj.[[Prototype]]
作为代替。其对应于Object.getPrototypeOf(obj)
。它不应与函数的func.prototype
属性混淆,后者指定在给定函数被用作构造函数时分配给所有对象_实例_的[[Prototype]]
。我们将在后面的小节中讨论构造函数的原型属性。
同时 mdn 上也提醒我们{ __proto__: ... }
语法与 obj.__proto__
访问器不同:前者是标准且未被弃用的。
const o = {
a: 1,
b: 2,
// __proto__ 设置了 [[Prototype]]。它在这里被指定为另一个对象字面量。
__proto__: {
b: 3,
c: 4,
},
};
// o.[[Prototype]] 具有属性 b 和 c。
// o.[[Prototype]].[[Prototype]] 是 Object.prototype(我们会在下文解释其含义)。
// 最后,o.[[Prototype]].[[Prototype]].[[Prototype]] 是 null。
// 这是原型链的末尾,值为 null,
// 根据定义,其没有 [[Prototype]]。
// 因此,完整的原型链看起来像这样:
// { a: 1, b: 2 } ---> { b: 3, c: 4 } ---> Object.prototype ---> null
console.log(o.a); // 1
// o 上有自有属性“a”吗?有,且其值为 1。
console.log(o.b); // 2
// o 上有自有属性“b”吗?有,且其值为 2。
// 原型也有“b”属性,但其没有被访问。
// 这被称为属性遮蔽(Property Shadowing)
console.log(o.c); // 4
// o 上有自有 属性“c”吗?没有,检查其原型。
// o.[[Prototype]] 上有自有属性“c”吗?有,其值为 4。
console.log(o.d); // undefined
// o 上有自有属性“d”吗?没有,检查其原型。
// o.[[Prototype]] 上有自有属性“d”吗?没有,检查其原型。
// o.[[Prototype]].[[Prototype]] 是 Object.prototype 且
// 其默认没有“d”属性,检查其原型。
// o.[[Prototype]].[[Prototype]].[[Prototype]] 为 null,停止搜索,
// 未找到该属性,返回 undefined。
创建对象
1 .创建对象最简单的方式就是使用对象直接量
let empty = {}; // An object with no properties
let point = { x: 0, y: 0 }; // Two numeric properties
let p2 = { x: point.x, y: point.y+1 }; // More complex values
let book = {
"main title": "JavaScript", // These property names include spaces,
"sub-title": "The Definitive Guide", // and hyphens, so use string literals.
for: "all audiences", // for is reserved, but no quotes.
author: { // The value of this property is
firstname: "David", // itself an object.
surname: "Flanagan"
}
};
Object.create()
2. Object.create()
可以用来创建对象,可以通过传入参数 null 来创建一个没有原型的新对象,但通过这种方式创建的对象不会继承任何东西,甚至不包括基础方法,比如 toString(),也就是说,它将不能和“+”运算符一起正常工作:
let o2 = Object.create(null); // o2 inherits no props or methods.
如果想创建一个普通的空对象(像通过 或 new Object() 创建的对象),需要传入 Object.prototype:
let o3 = Object.create(Object.prototype); // o3 is like {} or new Object().
根据红宝书上的描述实现 Object.create
可以粗略实现:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
3. class 关键字
class Person {
constructor() {}
}
let p = new Person()
4. 工厂模式、构造函数模式、原型模式等设计模式
工厂模式
function createPerson(name, age, job) {
let o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.sayName = function() {
console.log(this.name);
};
return o;
}
let person1 = createPerson("Nicholas", 29, "Software Engineer");
let person2 = createPerson("Greg", 27, "Doctor");
缺点: