首先,我们有必要了解一下JavaScript在设计时为何没有类的概念。
我参考阅读了 两篇博文:
1.《JavaScript继承机制的设计思想 》http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
2.《理解JavaScript面向对象的思路》http://www.cnblogs.com/winter-cn/archive/2009/05/16/1458390.html
了解到94年网景公司(Netscape)在发布了浏览器的某一个版本后,出现了一个问题:表单的验证是由服务器来完成了,很消耗资源。因而急需一种浏览器脚本语言,能跟网页互动,在用户端就能做一些简单的表单验证,从而分担服务器的压力。这个任务交给了工程师Brendan Eich。当时面向对象程序设计语言(C++和Java)方兴未艾,他受其影响使JavaScript也面向了对象并引入了new操作符和构造函数。但他没有引入类的概念,因为那样一来,JavaScript就成为完整的面向对象编程语言了,就不简单易学了,而是引入了prototype(“原型”的意思)。
具体的实现方式在对象创建时,在创建对象时new后跟的是构造函数(而不是类),同时为每个对象规定一个私有属性[[prototype]],并使其指向构造函数的prototype属性所指向的对象,即原型对象。当读取一个对象的属性时,如果对象本身没有这个属性,会尝试访问原型对象的相应属性。具体实现中,[[prototype]]所指向的对象仍然可以有[[prototype]],实际的访问就是一个链式的操作,直到找到这个属性或者[[prototype]]为空为止,所以常常听到原型链的说法,JavaScript主要就是通过它来实现继承的。为了防止[[prototype]]出现循环,JS引擎会在任何对象的[[prototype]]属性被修改时检查。按照标准,这个[[prototype]]语言使用者是无法访问的,不过FireFox的JS引擎把[[prototype]]暴露出来,作为公有属性"__proto__"。另外,为了类型识别,对构造函数(其实不仅限于构造函数,而是对所有的函数)规定了prototype属性(不同于对象,函数的prototype属性可以直接访问),指向原型对象,而所有的原型对象都会在创建一个新函数时自动获得一个constructor属性,它默认指向构造函数。
总结一下,实例、原型对象、构造函数三者之间的关系。那就是:
1.每个构造函数都有一个指向原型对象的指针(prototype属性);
2.每个原型对象都有一个指向构造函数的指针(constructor属性);
3.每个实例(对象)都有一个指向原型对象的内部指针([[prototype]])。
下面探讨JavaScript中对象的创建。创建对象所采用的模式越来越好。
1.采用new Object()或对象字面量的模式创建对象。-----弊端:会产生大量重复的代码。
2.采用工厂模式。解决了创建多个相似对象的问题。----弊端:无法解决对象识别问题。
3.采用构造函数模式。解决了对象识别的问题-----弊端:同种引用类型的方法不能共享。
4.采用原型模式。实现了同种类型的属性共享。----弊端:当属性值本身又是引用类型时,共享时,不同的实例都持有同一份引用,都能对其操作,这样的属性不方便。
5.组合使用构造函数模式和原型模式。将公用的属性、方法放在原型对象里定义,将个性化的属性、方法放在构造函数里定义,从而最大限度地节省内存。
最后探讨JavaScript中的继承机制。实现继承所采用的范式也是越来越好。
1.原型链。重写原型对象,使其具有一个内部指针指向另一个类型的原型对象,从而实现继承。----弊端:当原型对象中包含有引用类型的属性值时,不方便(其弊端类似于创建对象时的模式4)。
2.组合继承。借用构造函数与原型链相结合。----弊端:两次调用了父类型的构造函数。
3.寄生组合式继承。采用寄生式继承的模式,使子类型的原型对象具有一个指向父类型原型对象的内部指针(这就是所谓的寄生),另外,在子类的构造函数中借用父类型的构造函数。这是开发人员普遍认为最理想的继承范式。
分享到:
相关推荐
通过使用apply()和call()方法,可以在将来新创建的对象上执行构造函数,从而实现继承。 优点: - 可以向超类型构造函数传递参数。 缺点: - 无法实现函数复用。 - 在超类型的原型中定义的方法,对子类型而言也是不...
原型(Prototype)是JavaScript实现继承的基础,每个对象都有一个`__proto__`属性,指向创建它的构造函数的原型对象。通过原型,子类可以共享父类的属性和方法,减少了代码的重复。此外,JavaScript的灵活性允许...
在传统面向对象的语言中,有两个非常重要的概念 - 类和实例。 类定义了一类事物公共的行为和方法;而实例则是类的一个具体实现。 我们还知道,面向对象编程有三个重要的概念 - 封装、继承和多态。 但是在...
JavaScript还可以通过原型对象来实现继承。 原型对象 在JavaScript中,每个函数对象都有一个prototype属性,该属性指向函数的原型对象。原型对象是一个对象,它包含了构造函数的所有实例对象所共享的属性和方法。...
### JavaScript 创建对象与对象继承的有效方法 #### 一、引言 JavaScript 是一种基于原型的语言,这使得其处理对象和继承的方式与传统的面向对象编程语言有所不同。本文将深入探讨 JavaScript 中创建对象及对象继承...
总的来说,`zInherit`是JavaScript对象继承的一种实现,它利用原型链实现继承关系,使得子类可以继承和扩展父类的属性和方法。理解并熟练掌握这种继承方式,对于深入理解JavaScript的OOP特性以及编写高效的代码至关...
每个JavaScript对象都有一个内部的[[Prototype]]属性,通常可以通过`__proto__`或`Object.getPrototypeOf`访问。当试图访问对象的一个属性时,如果该属性不存在于当前对象,JavaScript会向上搜索原型链,直到找到该...
使用`Object.create()`方法可以创建一个新对象,其`__proto__`属性指向指定的对象,从而实现继承。这是一种更简洁、更纯粹的继承方式,但同样不支持方法的继承。 4. 组合继承(Composite Inheritance) 组合继承...
在JavaScript中,面向对象编程是实现复杂功能和代码复用的关键。继承是面向对象的核心特性之一,它允许一个对象(子类)从另一个对象(父类)获取属性和方法,从而形成类之间的层次结构。本篇文章将深入探讨...
在JavaScript中,对象可以直接从其他对象继承属性和方法,而不是通过类的实例化。这种继承机制使得JavaScript具有更强的表现力和灵活性,尤其在代码复用和类型安全方面。 类型安全和代码复用是类继承的主要原因。在...
- **第三章:JavaScript中的类和对象**:详细介绍如何使用JavaScript创建类和对象。 - **第四章:继承**:探讨JavaScript中实现继承的不同方式。 - **第五章:封装和私有性**:讲解如何在JavaScript中实现封装以及...
本文将详细探讨三种主要的创建JavaScript对象的方法,并结合“源码”与“工具”的概念,来深入理解这些方式在实际开发中的应用。 一、字面量(Literal)方式 这是最简单直接的对象创建方式,通过大括号 `{}` 将属性...
5. **继承(Inheritance)**:JavaScript通过原型链实现继承。子类的原型会指向父类的实例,从而继承其属性和方法。ES6的`class`语法也支持`extends`关键字进行继承。 ```javascript class Employee extends ...
这个文件可能包含了一些示例代码,用于演示上述的JavaScript对象创建、类定义和继承的实践。通过查看和运行这些代码,你可以更好地理解这些概念并应用到实际项目中。 总结来说,JavaScript对象创建涉及字面量、构造...
在JavaScript中,可以使用`JSON.stringify()`将对象转换为JSON字符串,`JSON.parse()`将JSON字符串解析回JavaScript对象。 ### 其他知识点 - `this`关键字:在函数中,`this`指代调用该函数的对象。在全局作用域或...
JavaScript作为一门具有面向对象特性的脚本语言,虽然没有传统意义上类的概念,但它通过其他方式实现了对象的创建和继承。在JavaScript中创建对象主要涉及以下几种模式: 1. 工厂模式 工厂模式是最早期的对象创建...
JavaScript没有类,但可以通过原型(prototype)机制来实现继承。以下是两种经典的JavaScript面向对象继承方法的详细解释: 1. **基于原型的继承**: 这种方法是JavaScript最基础的继承方式,通过`prototype`属性...
在没有类的情况下,JavaScript使用原型式继承模拟面向对象概念。`Object.create`函数可以创建一个新的对象,该对象的原型是传入的第一个参数。 5. **构造函数、实例和`this`关键字** `this`在JavaScript中表示...
在JavaScript中,可以通过构造函数或类来创建对象,并通过定义方法来隐藏具体的实现细节。此外,ES6引入了类的概念,进一步增强了抽象的能力。 **示例代码:** ```javascript class USBDevice { constructor(name)...