前言
CSDN博客:javascript面向对象编程(继承和复用)
继承,代码复用的一种模式。和其它高级程序语言相比,javascript有点点不一样,它是一门纯面向对象的语言,在JS中,没有类的概念,但也可以通过原型(prototype)来模拟对象的继承和多态。根据javascript对象的特点,JS中的继承又可以分类为引用对象继承和实例对象继承。
引用对象继承,子引用类型继承父引用类型,然后通过子引用类型生成的实例对象,具有父引用类型的特性。 而实例对象继承,继承得到的对象都具有父实例对象的所有属性和方法,其实就是指对象的复制和克隆。
- 默认继承模式
- 借用构造函数模式
- 借用构造函数和设置原型模式
- 共享原型模式
- 临时原型模式
- 借用构造函数+临时原型模式
实例对象继承也有以下几种实现模式:
- 临时-原型继承
- 借用和绑定实现继承(其实是复用)
引用对象继承-默认继承模式
默认继承模式很简单,如果要C继承P,实现代码:
function Parent(name) {
this.name = name || 'Adam';
}
Parent.prototype.say = function() { return this.name;};
function Child(name) { };
function inherit(C , P) {
C.prototype = new P();
}
var c = new C ('xiaoxin' );
alert(c.say()); // 'Adam'
模式特点:
- C不仅继承了P的所有属性,同时还继承了P的原型(P.prototype)的所有属性,但有时候,我们只想继承P的原型的属性;
- C的构造函数不能传递参数,也就是说无法通过给C构造方法传递参数,C将参数传递到P的构造方法(个人认为这个问题不大大,实现方式二 可以解决这个问题)。
引用对象继承-借用构造函数
借用构造函数模式,其实就是指采用Apply或Call来让子对象继承父对象的属性,具体看下面例子:
function Article(name) {
this.name = name;
this.tags =['js','css'];
}
var article = new Article('parent');
function BlogPost() {}
BlogPost.prototype = article;
var blog = new BlogPost();
function Parent2 (name) { //父对象2
this.name2 = name;
}
function StaticPage(name) {
Article.apply(this,arguments); // 子对象可以继承多个父对象
Parent2(this,arguments); // 子对象可以继承多个父对象
}
var page = new StaticPage("page");
alert(article.hasOwnProperty('tags')); //true
alert(blog.hasOwnProperty('tags')); // false 说明:子对象不能继承父对象的prototype中的属性
alert(page.hasOwnProperty('tags')); //true 说明:子对象继承了父对象的属性
blog.tags.push('html');
page.tags.push('php');
alert(article.tags.join(',')); // js,css,html 说明:默认继承模式可以修改父对象的属性; 而借用构造函数模式中,对象继承的属性仅仅是一个副本
模式特点:
- 通过这种方式继承,每个子对象都具有父对象的属性,且该属性是父对象属性的副本(非引用),所以它不会出现子对象通过修改继承的属性而导致父对象属性被覆盖的风险;
- 通过这种方式实现的继承,一个子对象可以继承多个父对象;
- 子对象只能继承父对象的属性,但是不能继承父对象的prototype对象的属性。
引用对象继承-借用构造函数和设置原型
该模式其实就是默认继承模式和借用构造函数的组合所实现的一种模式,该模式可以解决先前两个模式存在的一些问题,具体见下例:
function StaticPage(name) {
Article.apply(this,arguments); // 子对象可以继承多个父对象
// Parent2(this,arguments); // 此时 子对象可以继承多个父对象
}
StaticPage.prototype = new Article(); //设置原型
模式特点:
- 这种模式会导致父对象的属性会被继承两次,导致效率低下。
引用对象继承-共享原型原型
共享原型模式的原理就是:子类对象和父类对象共享一个原型,即父类对象的原型,具体见下面例子:
StaticPage.prototype = Article.prototype; //共享原型
模式特点:
- 这种模式几乎近完美了,它基本上没有以上模式存在的问题。只是有一点需要注意,那就是由于子对象和父对象共享一个原型,如果某个子对象对原型里的属性进行了修改,会导致父对象的原型也发生变化,从而导致所有的子对象实例都会发生变化。
引用对象继承-临时原型模式
前面说了,默认继承模式可能会继承父类对象一些你不想继承的属性,而共享原型模式有存在父类对象属性被修改的风险,怎么办呢?临时构造函数模式则很好的解决了以上存在的问题。临时构造函数模式的原理是: 只继承父类对象的原型对象; 不将父类对象原型直接赋值给子类对象的prototype属性,而是引用一个第三方函数对象,将父类函数对象的prototype赋值给这个第三方函数对象的prototype,然后将这个第三方函数对象的实例对象作为子对象的prototype。
说得有点拗口,具体看下面例子吧:
function inherit(C,P) { //可通过Object.create()方法简化下面代码(ES5)
var F = function() {}; //构造一个第三方临时函数
F.prototype = P.prototype // 原型赋值 (要继承的东西都放到protype对象里)
C.prototype = new F(); //如此,则解决了默认继承和原型共享继承所带来的问题
C.uber = P.prototype ; //可加 可不加 加上后,可以让在对象可以访问父类(超类)
C.prototype.constructor = C; // 重置constructor属性
引用对象继承-用构造函数+临时原型模式
这种方法,就是为了解决借用构造函数和设置原型存在的父对象的属性被继承两次导致效率低下的问题,它是怎么实现的呢?看下面代码:
function Child() {//继承Parent对象里的属性
Parent.call(this);
}
//inherit可参照上面章节代码
inherit(Child, Parent);
这种方法是最合适,也是用得最广的继承模式,在nodejs中,推荐采用这种方式来实现继承。比如,我想继承EventEmitter引用类型,代码如下:
function MyEvent() {
events.EventEmitter.call(this);
}
util.inherits(MyEvent, events.EventEmitter);//使这个类继承EventEmitter
实例对象继承-原型继承
现代继承和传统继承不同,它指得不是类的继承,而是指对象的继承,其实质就是:创造出一个对象,和父对象具有相同的属性 。 示例:
function object(parent) { //对象继承的公共方法
var F = function() {}; //创建一个临时函数对象
F.prototype = parent;
return new F(); //返回一个新的实例对象
}
function Person() {
this.name = 'xiaoxin';
}
Person.prototype.getName = function() { return this.name; }
var pa = new Person();
var kid = object(pa);
alert(pa.name); // xiaoxin 继承了父对象属性
alert(kid.getName()); //xiaoxin 继承了父对象的prototype属性
实例对象继承-对象复制(克隆)
对象的复制也是一种对象继承的方式(注意JS中现代继承的意义)。下面是一个简单的浅克隆方式,浅克隆相对简单,如果需要进行精确的对象复制,建议采用深克隆。Jquery中就应用了大量的深度克隆来实现 jquery 功能和插件的扩展。
function extend(parent,child) { //浅克隆的简单实现
var att ;
child = child || {};
for(i in parent) {
if(parent.hasOwnProperty(i)) {
child[i] = parent[i];
}
}
return child;
}
实例对象继承-借用和绑定
前面说了对象复制这种模式,它对父对象所有属性进行克隆复制,生成一个子对象,从而实现了父对象中属性代码的复用。但是,有时,我们并不需要复用父对象的所有属性,而是仅仅只需要使用某个属性而已,此时我们可以考虑采用借用模式来实现。借用模式的原理:采用apply或call来实现对象中方法的复用。
具体看下面一个例子:
//假如 我们需要复用数组对象的slice()方法,用来截取类数组arguments中的一段
function f() {
var args = [].slice.call(arguments,1,3);// 只复用Array中的slice方法。
// var args = Array.prototype.slice.call(arguments,1,3); //需要输入更长的字符,但是节省了创建一个数组的开销
return args;
}
f(1,2,3,4,5,6); //返回 [2,3]
面上面的模式用来普通的方法(方法类不含this关键字)是没有问题的,但是如果复用的方法内包含有this关键字,且该方法又作为全局方法或回调函数传递,则会出现一点点小问题,具体看下面示例:
var one = {
name : "object",
say: function(greet) { return greet+","+this.name; } //被复用的方法 里面包含this关键字
}
one.say('hi'); // hi,object
var two = { name: 'another object' };
one.say.apply(two, ['hello']) ; // hello,another object //这是没问题的,相当于已经绑定对象到 two了
var say = one.say;
say('hello'); //hello,underfined 未绑定对象,导致 this为全局对象,所以取不到name值
var yetanother = {
name: 'yet another object',
method: function(callback) {
return callback('Hola');
}
}
yetanother.method(one.say); // Hola,underfined 未绑定对象,导致 this为全局对象,所以取不到name值
面以上例子表明:如果要复用方法,一定要将复用的对象和被复用的方法绑定,而全局对象或回调函数的形式是未绑定的,如果使用前要绑定呢?要和two对象进行绑定呢?
function bind(method,obj) {
//注意这个红色的return 放回的是一个function方法
return function() {
//绑定过程
return method.apply(obj,[].slice.call(arguments));
};
}
//相当于 var say = function() { return one.say.apply(two,[].slice.call(arguments));}
var say = bind(one.say,two);
say('hello'); //hello,another object
版权声明:本文为博主原创文章,未经博主允许不得转载。
相关推荐
在提供的资源中,《代码之美》PDF文件可能包含了关于编程实践和代码风格的指导,而《Javascript面向对象编程》PPT可能更具体地阐述了JavaScript OOP的细节和示例。学习这些材料将有助于深入理解JavaScript的面向对象...
### JavaScript面向对象编程详解 #### 一、现代JavaScript概述 随着技术的发展,JavaScript这门语言已经从最初的简单脚本语言成长为现在广泛应用于Web前端、后端甚至桌面应用的强大编程工具。现代JavaScript具备...
JavaScript 面向对象编程是前端开发中至关重要的一部分,它基于OOP(Object-Oriented Programming)的概念,允许开发者创建可复用、可维护的代码结构。JavaScript 的OOP与传统面向类的语言(如Java、C++)有所不同,...
JavaScript 面向对象编程是该语言的核心特性之一,它允许开发者通过对象和它们的属性、...这就是JavaScript面向对象编程的基本应用。通过掌握这些知识,开发者能够更好地驾驭JavaScript,构建出高效、灵活的前端应用。
在JavaScript中,面向对象编程(Object-Oriented Programming,OOP)是其核心概念之一,帮助开发者创建复杂、可复用和易于维护的代码结构。下面我们将详细探讨JavaScript面向对象的基础知识。 1. **对象和数据类型*...
总结来说,JavaScript面向对象编程是现代Web开发不可或缺的一部分,掌握这些基本概念和技术对于提升JavaScript编程能力至关重要。通过学习和实践,开发者可以更好地理解和应用这些知识,构建高效、可扩展的前端和...
### JavaScript面向对象编程的核心概念与实践 #### 一、引言 JavaScript作为一种广泛应用于Web开发的语言,其灵活性和强大功能使其成为了前端工程师必备的技能之一。面向对象编程(OOP)作为软件工程中的一种核心思想...
JavaScript的面向对象编程(Object-Oriented Programming, OOP)是一种强大的编程范式,它允许开发者模拟现实世界中的实体,并通过...理解并熟练运用JavaScript的面向对象编程,是成为一名高级前端开发者的必备技能。
面向对象编程(Object-Oriented Programming, OOP)是JavaScript中的一个重要特性,它允许我们以类和对象的方式组织代码,提高代码的可维护性和复用性。在JavaScript中,我们可以通过构造函数和原型链来创建和扩展...
在JavaScript中,对象继承是实现面向对象编程(OOP)的关键特性之一。对象继承允许一个对象(子对象)从另一个对象(父对象或基对象)那里获取属性和方法,从而实现代码的复用和组织。`zInherit`是JavaScript中一种...
JavaScript 面向对象技术是实现复杂用户界面功能...尽管JavaScript的OOP模型与传统的类继承有所不同,但其原型链机制同样能够实现面向对象编程的核心原则,使得开发者能够利用这一强大的工具来创建复杂的前端交互功能。
在提供的示例代码中,展示了如何使用JavaScript面向对象的方法来操作DOM元素: 1. **直接操作DOM元素**: - 获取所有`div`和`p`元素,并分别设置它们的样式。 - 这里虽然没有显式地创建对象,但可以观察到...
它具有动态类型、原型继承和弱类型等特点,使得JavaScript在实现面向对象编程时与其他语言有着显著的区别。下面将详细介绍JavaScript中的面向对象知识,以及如何利用这些概念进行高效编程。 一、面向对象基础 1. ...
再者,JavaScript的原型继承机制是其面向对象编程的一大特色。通过原型链,一个对象可以继承另一个对象的属性和方法,实现代码复用。而ES6引入的类和模块系统,让JavaScript的面向对象编程更加符合传统编程范式,...
面向对象编程是程序设计的一种结构化方法,它将数据和操作数据的方法封装在一起,形成对象,以此提高代码的复用性和可维护性。 首先,了解基本的跨域解决方案。CORS(Cross-Origin Resource Sharing)是最常用的一...
面向对象编程(OOP)的核心是将数据和操作这些数据的方法结合在一起,形成独立的、可复用的实体——对象。与面向过程编程相比,面向对象更加关注数据和对象本身,而非具体的执行步骤。 在JavaScript中,对象是通过...
在JavaScript中,面向对象编程(OOP)是一种强大的设计模式,可以用来构建复杂、可复用的代码结构。本文将详细介绍如何使用JavaScript的面向对象方法实现拖拽特效,并结合继承的概念,为初学者提供深入的理解。 一...
此外,JavaScript的面向对象编程(OOP)也是重要内容。类和对象的概念,继承、封装和多态性等面向对象特性,都是提高代码复用性和可维护性的关键。原型链、构造函数和实例化等概念在JavaScript中的应用也是学习的...
首先,JavaScript是一种解释型的、面向对象的、动态类型的脚本语言。它主要应用于Web浏览器,但也可在服务器端(如Node.js)和其他环境运行。JavaScript的学习应从基础语法开始,包括变量声明、数据类型(如字符串、...