JavaScript是一种功能强大的语言,起初它只是用于在浏览器中完成一定的Dom操作和特殊效果。随着AJAX和RIA技术的广泛普及,JavaScript发挥了越来越重要的作用,JavaScript的代码量越来越大,对可维护性的要求也越来越高。JavaScript提供了特有的类机制,但是在语法习惯上与传统面向对象的语言有很大的不同,这使得不少的JavaScript开发人员感到困惑,本文将会对JavaScript常见的类功能进行介绍。
1.JavaScript定义类及实例化
在JavaScript的语法中,并没有类似于Class的类定义关键字,而是使用与普通方法一样的function来定义类,所以定义普通的方法与定义类有着类似的语法(这使得刚接触JavaScript的开发人员会感到很难理解,关于如何判断function是要作为类的定义,可以查看这篇文章。)
//定义一个普通方法
function testSimpleFunction(){
alert("This is a simple function!");
}
testSimpleFunction();//调用方法
//定义一个类
function Person(name,age){
this.name = name;
this.age = age;
this.aboutMe = function(){
alert("I’m a person!My name is "+this.name+",My age is "+this.age+"!")
}
}
var personObject = new Person("levin",30);//实例化该类,得到一个对象
personObject. aboutMe();//调用对象的方法
JavaScript是基于原型的语言,每个类(即构造函数)都有一个prototype属性指向该类对应的原型对象,而实例化得到的对象会拥有该类原型中的属性和方法。常用的定义类的方式如下:
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function(){
alert(this.name);
}
var person = new Person("levin",30);
person.sayHello();//调用原型中的方法
对象在进行属性和方法访问时,首先会在对象内部查找,如果找不到,会在其构造函数原型中进行进一步的查找。基于这样的机制,对象从原型得到的属性和方法可以进行重写覆盖,对象就拥有与原型同名的属性和方法,而对于通过此类实例化的其它对象,则不会受其影响:
person.sayHello = function(){
alert("My own name is "+this.name);
}
person.sayHello();
var anotherPerson = new Person("zhangwb",30);
anotherPerson.sayHello();
在本例中,person对象和anotherPerson对象尽管都是通过Person类实例化而来,但是他们在调用sayHello方法时会有不同的结果。这就是因为person对象重写了从构造函数原型中继承而来的sayHello方法。
2.继承
在JavaScript中没有直接实现继承的关键字,因此关于继承有多种的实现方式,代表性的是类式继承和原型式继承,对于这两种继承方式,我们都会进行简单的介绍。
首先看一下类式继承。如果我们有一个名为Employee类想要继承Person类,一般的写法如下:
function Employee(name,age,workExperience){
Person.call(this,name,age)
this.workExperience = workExperience;
}
Employee.prototype = new Person();
Employee.prototype.constructor=Employee
Employee.prototype.getInput = function(){
return 5000;
}
var employee =new Employee("employee levin",30,4);
employee.sayHello();
alert(employee.getInput());
在这个例子中,我们定义名为Employee的类,要求继承Person类,该类有三个初始化参数,其中前两个与Person类一致,而第三个参数workExperience是该类特有的,Employee除了要继承Person类的属性和方法,还要求定义名为getInput的方法。
在本例中,我们在Employee的构造函数中,调用了Person的构造函数,并传递了适当的参数,从而实现了属性的继承。对于Person方法的继承,我们是通过调整Employee原型链的方式来达到的,首先将Employee类的prototype所指向的对象设置为一个Person实例,这样就使得Employee能够使用Person原型中定义的方法,但是这也把Employee原型中的构造函数指向了Person,因此我们需要将其进行重新置为Employee。通过以上的操作,Employee实现了对Person的继承,而Employee要定义新的方法,只需要在其prototype属性中继续追加即可。
这样的继承方式缺乏通用性,对于每个实现的继承的地方都写很多的类似代码,另外在调整原型链的时候,需要实例化一个父类的实例,而这是没有必要的,因为我们想要的仅仅是父类的原型链。因此我们可以写一个通用的方法:
function extend(subClass,superClass){
var F = function(){};
F.prototype = superClass.prototype;
subClass.prototype = new F();
subClass.prototype.constructor = subClass;
subClass.superClass = superClass.prototype;
if(superClass.prototype.constructor == Object.prototype.constructor){
superClass.prototype.constructor = superClass;
}
}
在这个方法中,传入两个参数,分别为子类和父类,我们首先定义了一个新的构造函数,让该函数的prototype设置为父类的prototype,然后子类的prototype属性指向了一个F的实例,这样就能够在不实例化父类的情况下完成原型链的调整,另外我们在子类中定义了一个名为superClass的属性,指向了父类的原型,从而可以通过子类调用到父类的方法。此时要实现Employee和Person的继承关系就容易许多了:
function Employee(name,age,workExperience){
Employee.superClass.constructor.call(this,name,age)
this.workExperience = workExperience;
}
extend(Employee,Person);
Employee.prototype.getInput = function(){
return 5000;
}
其次,我们来看一下原型式继承。原型式继承与类式继承以及其它语言的继承方式都有着很大的差异。在原型式继承中,不会再使用类来定义对象结构,而是直接使用字面量,以后创建的对象都以此为原型。如有以下的Person原型对象:
var Person={
name:"levin",
age:30,
getName:function(){
alert(this.name);
}
}
要创建新对象时,需要调用以下的方法:
function object(o) {
function F() {}
F.prototype = o;
return new F();
}
在这个方法中,我们定义了一个空的构造函数,将传入对象作为构造函数的prototype属性,从而生成的新对象能够访问到原型提供的属性和方法。如我们要创建一个Person的实例:
var person = object(Person); //得到Person的实例
person.getName();
而继承的实现也有赖于object方法,如要实现和前面介绍相同功能的Employee类,只需执行以下的代码即可:
var Employee = object(Person);
Employee.workExperience = 4;
Employee.getInput = function(){
alert(5000)
}
var employee = object(Employee);//得到Employee的实例
employee.getInput()
以上简要介绍了JavaScript两种常见的继承方式,无论哪种方式与传统的面向对象语言都有很大的差异,这需要开发人员对JavaScript有较为深入的了解,而一些常用的框架都对JavaScript的类机制进行了封装,这样我们就能够更方便的定义和使用JavaScript类。
在其它面向对象语言中,发挥重要功能的接口功能,在JavaScript中没有对应的关键字实现,但是有很多的替代方案进行了模拟,《JavaScript设计模式》一书对此有所介绍,感兴趣的读者可以参考。
根据以上的介绍,我们了解到在JavaScript中实现类机制需要对该语言有更为深入的掌握,而JavaScript作为一种动态语言,也提供了其它静态面向对象语言所难以实现的功能,这也许正是其有趣和吸引人的地方吧。
参考资料:
《JavaScript权威指南》 David
Flanagan著 张铭泽译
《JavaScript设计模式》 Ross
Harmes、Dustin
Diaz著 谢廷晟译
http://javascript.crockford.com/prototypal.html
http://javascript.crockford.com/inheritance.html
http://docs.dojocampus.org/
http://blog.csdn.net/dojotoolkit/
http://dojotoolkit.org/
分享到:
相关推荐
JavaScript 事件机制详细研究 JavaScript 事件机制是指浏览器中发生的各种事件,例如点击、鼠标悬停、键盘输入等,JavaScript 通过捕捉这些事件来执行相应的操作。本文将详细介绍 JavaScript 事件机制的实现方式和...
JavaScript 运行机制 JavaScript 运行机制是指 JavaScript 代码在浏览器或 Node.js 环境中执行的过程。这个机制涉及到变量作用域、函数执行、上下文创建和垃圾回收等多个方面。 一、全局执行上下文 在 JavaScript...
JavaScript是一门基于原型的语言,它不像其他面向对象的语言那样具有类的概念,而是通过原型链来实现继承。原型链是JavaScript继承机制的核心,它允许一个对象从另一个对象中继承属性和方法。通过原型链,JavaScript...
### JavaScript内存机制详解 #### 简介 在探索JavaScript内存机制之前,我们先了解一些基础知识。每一种编程语言都有其独特的内存管理机制。例如,C语言提供了低级别的内存管理功能,如`malloc()`和`free()`等函数...
继承机制是面向对象编程的核心机制之一,它允许开发者创建一个新的类,继承自另一个类的所有属性和方法,从而实现代码的重用和简化。 JavaScript的继承机制与其他面向对象语言相比,有其独特之处。JavaScript的继承...
### JavaScript运行机制浅探 #### 一、引言 JavaScript是一种广泛应用于网页浏览器中的脚本语言,它在前端开发中的地位不可替代。由于其独特的运行机制,开发者常常遇到一些意料之外的行为。本文旨在深入探讨...
本文将深入探讨JavaScript的执行机制,包括事件循环(Event Loop)以及与之相关的概念,如setTimeout和Promise。 首先,JavaScript的单线程特性源于其在浏览器环境中的历史背景。为避免网页在处理复杂任务时冻结,...
JavaScript验证机制是Web开发中不可或缺的一部分,主要用于在用户提交数据前检查输入的有效性和格式。它大大提升了用户体验,减少了服务器端的负担,因为错误的输入可以在前端就得到及时纠正。在这个"JavaScript验证...
夯实基础上篇-图解 JavaScript 执行机制 本文主要讲述了 JavaScript 执行机制的基础知识,包括变量提升、执行上下文、调用栈等概念。本文通过 9 个 demo 和 18 张图,详细地解释了 JavaScript 执行机制的过程。 ...
要用ECMAScript实现继承机制,首先从基类入手。所有开发者定义的类都可作为基类。出于安全原因,本地类和宿主类不能作为基类,这样可以防止公用访问编译过的浏览器级的代码,因为这些代码可以被用于恶意攻击。
总的来说,JavaScript的类机制提供了面向对象编程的能力,包括属性、方法、实例化和静态属性。通过类,开发者可以更好地组织代码,实现复杂的功能,并模拟现实世界中的各种对象和行为。理解和掌握JavaScript类的概念...
基于JavaScript的消息管理机制探讨 本文探讨了基于JavaScript的消息管理机制,旨在提高消息管理的水平,为用户提供可靠安全的消息。文章首先介绍了消息管理机制的重要性,然后详细地描述了基于JavaScript的消息管理...
在 JavaScript 中,类(Class)是 ES6 引入的一种面向对象编程的概念,用于创建对象的模板。然而,有时我们可能需要将不同类的功能组合在一起,以实现更复杂的行为,这就引入了“类混合”(Mixins)的概念。 "合并 ...
8. **ES6及以后的版本**:涵盖了ECMAScript的新特性,如箭头函数、模板字符串、类、模块系统等,这些新特性极大地增强了JavaScript的现代开发能力。 9. **性能优化和调试**:指导开发者如何写出高性能的JavaScript...
- 事件委托:利用事件冒泡机制,将事件监听器添加到父元素,提高性能。 - 异步控制流:利用回调、Promise和async/await处理异步操作。 3. **JavaScript异步编程**: 异步编程是JavaScript的重要特性,用于处理...
在JavaScript中,并没有直接提供类的概念,而是通过原型来实现继承。本文将深入探讨JavaScript中的原型继承机制,帮助读者理解其中的关键概念及其工作原理。 #### 二、原型与构造函数 在JavaScript中,每个函数都...
在JavaScript中,有多种方式可以实现类(Class)的概念,这是面向对象编程的一个重要组成部分。本文将深入探讨“javascript写类方式之六”,并结合标签“源码”和“工具”,解析其中的原理与实践。 在JavaScript ...
最后,JavaScript的ES6及后续版本引入了许多新特性,如箭头函数、模板字符串、解构赋值、类和模块等。掌握这些新特性,能够让你的代码更现代,更符合最佳实践。 总的来说,《JavaScript语言精粹》涵盖了JavaScript...
错误处理机制章节介绍了JavaScript中的Error对象、throw语句、try...catch结构和finally代码块。良好的错误处理机制能够帮助开发者编写更加健壮的代码。 最后,编程风格章节强调了JavaScript编程中的风格问题,包括...