本文共 1953 字,大约阅读时间需要 6 分钟。
在前几篇文章中,我们已经学习了如何通过构造函数实现对象的继承关系。然而,今天我们将探索另一种方法——不使用构造函数的对象继承,这种方法虽然不如构造函数的优雅,但在某些特定场景下依然有其用途。
在 JavaScript 中,对象的继承关系主要通过两种方式实现:构造函数模式和对象混合式继承。然而,前者依赖于构造函数,而后者则不需要。我们需要明确什么是“非构造函数”的继承。
以简单的例子来说明:
var Chinese = { nation: '中国'};var Doctor = { career: '医生'}; 现在的问题是:如何让 Doctor 继承 Chinese 的属性,从而形成一个完整的“中国医生”对象?
object() 函数:实现对象继承的简便方法为了解决上述问题,Douglas Crockford 提出了一个名为 object() 的函数,它可以用来创建继承自其他对象的新对象。这个函数的基本工作原理是:将子对象的 prototype 属性设置为父对象,从而实现继承。
function object(o) { function F() {} F.prototype = o; return new F();} 使用这个函数的步骤如下:
object() 函数,传入父对象 Chinese:var Doctor = object(Chinese);
Doctor.career = '医生';
Doctor 对象已经成功继承了 Chinese 的属性。验证结果:
alert(Doctor.nation); // 输出: 中国
除了通过 prototype 实现继承,我们还可以通过拷贝的方式来实现对象继承。拷贝有两种主要方式:浅拷贝 和 深拷贝。
浅拷贝仅将父对象的 属性值 拷贝到子对象中,不会递归拷贝属性的引用类型(如数组或对象)。以下是一个实现浅拷贝的函数:
function extendCopy(p) { var c = {}; for (var i in p) { c[i] = p[i]; } c.uber = p; return c;} 使用示例:
var Chinese = { nation: '中国'};var Doctor = extendCopy(Chinese);Doctor.career = '医生'; 验证结果:
alert(Doctor.nation); // 输出: 中国
此时,Doctor 和 Chinese 共享同一个 nation 属性。如果对 Chinese 的属性进行修改,Doctor 的属性也会受到影响。这就是浅拷贝的局限性。
深拷贝则会递归地拷贝对象的所有属性,包括嵌套的数组和对象。以下是一个实现深拷贝的函数:
function deepCopy(p, c) { var copy = c || {}; for (var i in p) { if (typeof p[i] === 'object') { copy[i] = (Array.isArray(p[i])) ? [] : {}; deepCopy(p[i], copy[i]); } else { copy[i] = p[i]; } } return copy;} 使用示例:
var Chinese = { birthPlaces: ['北京', '上海', '香港']};var Doctor = deepCopy(Chinese);Doctor.career = '医生';Doctor.birthPlaces.push('厦门'); 验证结果:
alert(Doctor.birthPlaces); // 输出: 北京, 上海, 香港, 厦门alert(Chinese.birthPlaces); // 输出: 北京, 上海, 香港
此时,Doctor 和 Chinese 的 birthPlaces 属性互不影响,深拷贝成功。
在本次学习中,我们探索了两种不使用构造函数的对象继承方法:
object() 函数:通过设置子对象的 prototype 属性来实现继承。这些方法在某些特定场景下(如 jQuery 的继承机制)仍然有其独特的优势。
转载地址:http://hbqfk.baihongyu.com/