Javascript:继承和原型链

简介: <h3 id="javascript" style="margin:10px 0px 0px; padding:0px; font-size:1.3em; color:rgb(102,102,102); font-family:'Open Sans',HelveticaNeue-Light,'Helvetica Neue Light','Helvetica Neue',Helvetica,

JavaScript:继承和原型链(译)

原文:Inheritance and the prototype chain

译者:youngsterxyf

对于具备基于类的编程语言(如Java或C++)经验的程序员来说,JavaScript有点混乱,因为它是一种动态语言,并且不提供class的实现(虽然关键字class是保留的,不可用作变量名)。

说到继承,JavaScript只有一种结构:对象。每个对象都有一个内部链接指向另一个对象,这个对象称为原型 (prototype)。那个原型对象也有自己的原型,如此直到某个对象以null作为其原型。null,根据定义,没有原型,作为这种原型链的最后一环而存在。

以原型链实现继承

继承属性


JavaScript对象可看作是动态地装载属性(这里指自有属性)的”包包”,并且每个对象都有一个链指向一个原型对象。如下即为当尝试访问一个属性时发生的事情:

// 假设有个对象o,其原型链如下所示:
// {a: 1, b: 2} ---> {b: 3, c: 4} ---> null
// 'a''b'是o的自有属性。

// 本例中,someObject.[[Prototype]]指定someObject的原型。
// 这完全是一种标记符号(基于ECMAScript标准中所使用的),不可用于脚本中。

console.log(o.a);   // 1
// o有一个自有属性'a'吗?是的,其值为1
 
console.log(o.b);   // 2
// o有自有属性'b'吗?是的,其值为2
// o的原型也有一个属性'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]]为null,停止搜索,没有找到属性,返回undefined。
AI 代码解读

将一个属性分配给一个对象会创建一个自有属性。对于获取和设置属性的行为规则,唯一的例外是当一个继承而来的属性带有一个属性值获取器或设置器

继承”方法”

JavaScript没有以基于类的编程语言定义方法的形式出现的”方法”。JavaScript中,任何函数都可以作为一个属性被添加到一个对象。一个继承而来的函数,操作起来与任何其他属性相同,包括如上所示的属性隐藏(在这里,称为方法覆盖)。

当执行一个继承而来的函数时,this的值指向继承对象,而不是原型对象,该函数是原型对象的自有属性。

var o = {
a: 2,
m: function(b) {
return this.a + 1;
}
};
 
console.log(o.m()); // 3
// 这里当调用o.m时,'this'引用o

var p = Object.create(o);
// p是一个继承自o的对象
 
p.a = 12;   // 为p创建一个自有属性'a'
console.log(p.m()); // 13
// 这里调用p.m时,'this'引用p
// 因此,当p继承了o的函数m,'this.a'意味着p.a,p的自有属性'a' ##`创建对象的不同方式,以及由此产生的原型链`
AI 代码解读

以语法结构创建对象

var o = {a: 1};

// 新创建的对象o有Object.prototype作为其[[Prototype]]
// o没有名为'hasOwnProperty'的自有属性
// hasOwnProperty是Object.prototype的自有属性。因此o从Object.prototype继承了hasOwnProperty
// Object.prototype以null为其prototype。
// o ---> Object.prototype ---> null
 
var a = ["yo", "whadup", "?"];

// 数组继承自Array.prototype(它具有indexOf, forEach等方法)。
// 该原型链如下所示:
// a ---> Array.prototype ---> Object.prototype ---> null

function f() {
return 2;
}

// 函数继承自Function.prototype(它具有call,bind等方法):
// f ---> Function.prototype ---> Object.prototype ---> null ###使用构造器
AI 代码解读

JavaScript中,”构造器””就”是一个恰好以new操作符调用的函数。

function Graph() {
this.vertexes = [];
this.edges = [];
}

Graph.prototype = {
addVertex: function(v) {
this.vertexes.push(v);
}
};

var g = new Graph();
// g是一个带有自有属性'vertexes'和'edges'的对象。
// 执行new Graph()后,g.[[Prototype]]是Graph.prototype的值。
使用Object.create
AI 代码解读

ECMAScript 5引入了一个新方法:Object.create。调用这个方法会创建一个新对象。这个对象的原型是该函数的第一个参数:

var a = {a: 1};
// a ---> Object.prototype ---> null

var b = Object.create(a);
// b ---> a ---> Object.prototype ---> null
console.log(b.a);   // 1 (继承而来)

var c = Object.create(b);
// c ---> b ---> a ---> Object.prototype ---> null

var d = Object.create(null);
// d ---> null
console.log(d.hasOwnProperty);  // undefined,因为d并不继承自Object.prototype
AI 代码解读
相关文章
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
理解JavaScript中的原型链:基础与实践
【10月更文挑战第8天】理解JavaScript中的原型链:基础与实践
JavaScript 原型链的实现原理是什么?
JavaScript 原型链的实现原理是通过构造函数的`prototype`属性、对象的`__proto__`属性以及属性查找机制等相互配合,构建了一个从对象到`Object.prototype`的链式结构,实现了对象之间的继承、属性共享和动态扩展等功能,为 JavaScript 的面向对象编程提供了强大的支持。
Javascript如何实现继承?
【10月更文挑战第24天】JavaScript 中实现继承的方式有很多种,每种方式都有其优缺点和适用场景。在实际开发中,我们需要根据具体的需求和情况选择合适的继承方式,以实现代码的复用和扩展。
原型链在 JavaScript 中的作用是什么?
原型链是 JavaScript 中实现面向对象编程的重要机制之一,它为代码的组织、复用、扩展和多态性提供了强大的支持,使得 JavaScript 能够以简洁而灵活的方式构建复杂的应用程序。深入理解和熟练运用原型链,对于提升 JavaScript 编程能力和开发高质量的应用具有重要意义。
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
js实现继承怎么实现
【10月更文挑战第26天】每种方式都有其优缺点和适用场景,开发者可以根据具体的需求和项目情况选择合适的继承方式来实现代码的复用和扩展。
31 1
探索JavaScript原型链:深入理解与实战应用
【10月更文挑战第21天】探索JavaScript原型链:深入理解与实战应用
34 1
一文梳理JavaScript中常见的七大继承方案
该文章系统地概述了JavaScript中七种常见的继承模式,包括原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合继承等,并探讨了每种模式的实现方式及其优缺点。
一文梳理JavaScript中常见的七大继承方案
深入理解JavaScript原型链:从基础到进阶
【10月更文挑战第13天】深入理解JavaScript原型链:从基础到进阶
34 0