JavaScript默认采用原型继承。虽然没有类(class)的概念,它的函数(function)可以充当构造器(constructor)。构造器结合this,new可以构建出类似Java的类。因此,JavaScript通过扩展自身能模拟类式(class-based)继承。
JavaScript和其它面向对象语言一样,对象类型采用引用方式。持有对象的变量只是一个地址,而基本类型数据是值。当原型上存储对象时,就可能有一些陷阱。
先看第一个例子
var create = function() { function Fn() {} return function(parent) { Fn.prototype = parent return new Fn } }() var parent = { name: 'jack', age: 30, isMarried: false } var child = create(parent) console.log(child)
create工具函数实现了一个基本的原型继承,每次调用create都会根据parent对象去复制一个新对象,新对象全部的属性都来自于parent。这里parent有三个属性,都是基本数据类型:字符串,数字,布尔。
这时修改child看看会不会影响parent
child.name = 'lily' child.age = 20, child.isMarried = true console.log(child) console.log(parent)
结果如下
即修改child不会影响到parent。
再看看另外一个例子
var create = function() { function Fn() {} return function(parent) { Fn.prototype = parent return new Fn } }() var parent = { data: { name: 'jack', age: 30, isMarried: false }, language: ['Java'] } var child = create(parent) child.data.name = 'lily' child.data.age = 20 child.data.isMarried = true child.language.push('javascript') console.dir(child) console.dir(parent)
注意这里的parent的两个属性data,language都是引用类型,一个是对象,一个是数组。child仍然继承与parent,随后修改了child,结果如下
可以看到,此时parent也被修改了,和child的name,age等都一样了。这是使用原型继承时需要注意的。
使用继承时比较好的方式是:
1,数据属性采用类式继承(挂在this上),这样new时也可以通过参数配置
2,方法采用原型继承,这样能节省内存,同时子类重写方法也不会影响父类
下面是一个满足以上2点的写类工具函数
/** * @param {String} className * @param {String/Function} superCls * @param {Function} classImp */ function $class(className, superCls, classImp) { var p, supr if(superCls === '') superCls = Object function clazz() { if(typeof this.init == "function") { this.init.apply(this, arguments) } } p = clazz.prototype = new superCls() clazz.prototype.constructor = clazz clazz.prototype.className = className supr = superCls.prototype window[className] = clazz classImp.apply(p, [supr]) }
对象类型放在父类原型上时务必小心子类修改其,这时继承于该父类的所有子类的实例都将被修改。而这造出的bug很不容易发现。
ES5中加入了一个新API用来实现原型继承:Object.create。可以用它替代上面自实现的create函数,如下
var parent = { name: 'jack', age: 30, isMarried: false } var child = Object.create(parent) console.log(child)
相关推荐
原型继承的陷阱** - **属性覆盖**:如果一个对象直接修改了原型上的属性,会影响到原型链上的所有对象。 - **原型链深度**:过长的原型链可能导致性能问题,并使代码难以维护。 #### 三、ES6 中的类与继承 尽管...
总之,理解JavaScript原型继承的陷阱对于编写可维护和高效的代码至关重要。在设计对象模型时,应谨慎处理引用类型的属性,以防止不必要的共享状态,同时利用原型链来优化方法的继承。通过正确地划分数据属性和方法,...
总的来说,JavaScript的面向对象继承机制灵活而强大,但同时也有一些复杂性和陷阱。理解和熟练掌握这些概念对于成为JavaScript的高级开发者至关重要。在学习过程中,通过实际编写代码,创建各种继承模式,以及研究...
在JavaScript中实现继承有多种方法,其中构造函数和原型链的方式是较为传统的一种,但在实际应用中存在一些问题和陷阱。本章节将深入分析这些常见的问题,并提出相应的解决方案。 首先,我们回顾一下使用构造函数和...
总的来说,JavaScript的对象和继承机制是其灵活性和强大性的体现,但同时也因为其独特的设计导致了一些误解和陷阱。理解这些概念对于深入学习和使用JavaScript至关重要。在实际开发中,开发者应根据需求选择合适的...
原型和原型链是JavaScript中实现继承的关键机制。通过原型链,一个对象可以继承另一个对象的属性和方法。书中将详细介绍如何利用`__proto__`和`Object.create()`来操作原型,以及如何使用`prototype`属性创建类似于...
2. **对象与原型**:JavaScript的原型继承机制是其独特之处。了解如何创建和使用原型链,以及如何有效地利用`__proto__`和`Object.create()`,可以更好地实现面向对象编程。 3. **函数与闭包**:闭包是JavaScript中...
JavaScript的继承机制基于原型链,这与传统的类继承有所不同。掌握如何使用`__proto__`、`Object.create()`和`prototype`属性实现继承是进阶学习的关键。 4. **对象** JavaScript的对象是键值对的集合,可以使用...
第四章主要讨论原型和对象,这是理解JavaScript继承机制的关键。通过解释原型链和构造函数,作者展示了如何利用这些特性来实现面向对象编程。他还提到了一些最佳实践,如使用Object.create()来创建新对象,以及避免...
JavaScript的原型链机制允许对象通过原型链继承其他对象的属性和方法。每个对象都有一个指向其原型对象的内部链接。当试图访问一个对象的属性时,如果该属性不存在于当前对象,JavaScript引擎会沿着原型链向上查找,...
此外,JavaScript的对象和原型机制是其独特之处,理解原型链、构造函数以及继承方式(如原型继承、组合继承、寄生组合继承、ES6的类继承)对于深入JavaScript至关重要。书中的修订版可能会涵盖最新的ES6及其后续版本...
《JavaScript忍者秘籍》第二版第7章样本的内容主要围绕JavaScript的对象导向编程和原型继承进行了深入探讨。在现代JavaScript开发中,理解这些概念对于编写高效、可维护的代码至关重要。 首先,文档提到了...
尽管实现类继承模型在JavaScript上相对容易,但要在JavaScript中实现原型继承则复杂得多。 在JavaScript中,对象是数据类型,并且可以作为哈希表使用,保存命名的键与值的对应关系。对象可以通过对象字面量(使用{}...
另外,JavaScript的原型继承和类概念,以及模块系统(CommonJS、ES6模块)也是理解和编写可维护代码的重要知识。 JavaScript还有一套强大的DOM(Document Object Model)操作API,允许开发者通过JavaScript动态地...
3. **原型与继承**:JavaScript的面向对象特性体现在其独特的原型链机制,通过理解原型和原型链,可以掌握对象的继承与扩展。 4. **DOM操作**:JavaScript与HTML的交互主要通过DOM(文档对象模型),学习如何选择...
鉴于面向对象编程在JavaScript中的实现与传统语言如Java或C++有所不同,书中可能还会介绍JavaScript特有的OOP特性,如原型继承、对象字面量、工厂模式以及后来的ES6新增的类语法等。 由于内容片段包含了版权声明和...
书中讲解了原型继承、构造函数、原型链以及更现代的类和模块系统。此外,还讨论了JSON(JavaScript Object Notation)在数据交换中的应用。 4. **错误处理**:JavaScript中的异常处理是程序健壮性的重要组成部分。...
3. **原型和继承**:JavaScript使用原型链实现对象的继承。每个对象都有一个原型,可以通过`__proto__`或`Object.getPrototypeOf`访问。通过原型,对象可以共享属性和方法,实现代码复用。 4. **函数和函数表达式**...