JavaScript之原型继承prototype
2015-02-08 17:52
405 查看
JavaScript的原型链,之前也用过,但对其中的原理一直没有深究,这次通过学习node.js,然后再回过头来系统的学习JavaScript,发现JavaScript的原型链机制是一个十分有趣的机制
我们都知道,JavaScript的对象机制和C类语言是由很大区别的,而其中一个很大的区别就是JavaScript是使用原型链来实现继承的
一. 原理
prototype是JavaScript对象的一个属性,注意这里是对象,而不是对象实例
可以看到,对象实例化之后,就不再包含prototype这个属性了,所以y.prototype = xxxx;是没有意义的,就只是多了一个prototype属性而已,而这个属性是不属于JavaScript内部的原型链机制的
另外,当要给原型赋值的时候,等号的右边一定是一个实例化好的对象,这就像C++的继承机制,当实例化一个类时,首先要实例化他的父类,所以等号右边就相当于是已经实例化好的父类,比如:
看看下面一张图:
可以看到,左边对象的prototype指向右边对象实例,而对象实例通过一个私有属性proto来访问父类,而Object对象是JavaScript的根对象,所以它的prototype指向一个空的对象实例,这就是JavaScript原型继承的机制
二. 使用
1.继承
这样,y就继承了x的print函数,属性也是如此
不过要注意,y只能继承对y.prototype所添加的属性和方法,比如下面的继承是无效的:
另外,想要继承函数内部的方法要格外小心,先看一个例子:
再看另一个例子:
2.节省空间和提高效率
对一个对象添加方法,一个直接的写法是:
PS:这里的几个例子都用了new 函数名()的方法来创建一个对象实例,其实这种方法在很多书上是不被推荐使用的,因为new方法只是JavaScript原型链继承机制向C类继承机制靠拢的一个手段,结果就是:It is the worst of both worlds
3.扩展原有的类库函数
由于JavaScript可以很方便地向一个对象添加方法,所以,我们可以对基本对象的原型添加方法,那么,所有继承这些基本对象的对象实例就将拥有这些方法
比如,我想给Number对象添加一个取整的方法:
之后就可以在所有的继承于Number对象的实例处使用这个方法了
当然,扩展类库函数并不是特别推荐使用,因为有人说这样会破坏封装,而且还要特别注意函数是否已经被声明过,不过,这样写的确会简化某些操作
三. 一些很好的文章
1.浅析Javascript原型继承 这篇文章对JavaScript原型继承有一个很好的讲解
2.JavaScript秘密花园 这篇文章对JavaScript的语法机制有一个全面系统的讲解,十分推荐!
我们都知道,JavaScript的对象机制和C类语言是由很大区别的,而其中一个很大的区别就是JavaScript是使用原型链来实现继承的
一. 原理
prototype是JavaScript对象的一个属性,注意这里是对象,而不是对象实例
var x = function(){}; console.log(typeof x.prototype); //object console.log(typeof (new x()).prototype); //underfined
var y = {}; console.log(typeof y.prototype); //underfined console.log(typeof Array.prototype); //object
可以看到,对象实例化之后,就不再包含prototype这个属性了,所以y.prototype = xxxx;是没有意义的,就只是多了一个prototype属性而已,而这个属性是不属于JavaScript内部的原型链机制的
另外,当要给原型赋值的时候,等号的右边一定是一个实例化好的对象,这就像C++的继承机制,当实例化一个类时,首先要实例化他的父类,所以等号右边就相当于是已经实例化好的父类,比如:
var x = function(){}; var y = function(){}; y.prototype = new x(); //等号右边是一个实例化好的父类
看看下面一张图:
可以看到,左边对象的prototype指向右边对象实例,而对象实例通过一个私有属性proto来访问父类,而Object对象是JavaScript的根对象,所以它的prototype指向一个空的对象实例,这就是JavaScript原型继承的机制
二. 使用
1.继承
var x = function(){}; var y = function(){}; y.prototype = new x(); y.prototype.print = function() { console.log("I get it!"); }; (new y()).print(); //I get it!
这样,y就继承了x的print函数,属性也是如此
不过要注意,y只能继承对y.prototype所添加的属性和方法,比如下面的继承是无效的:
var x = function(){}; var y = function(){}; x.print = function() { console.log("I get it!"); }; y.prototype = new x(); x.print(); //I get it! (new x()).print(); //报错 (new y()).print(); //报错为什么会错呢,一般只会对对象的实例添加属性和方法,而不会对对象添加属性和方法,否则,只有对象本身能够访问该方法,而对象的实例是访问不到的,更不用说继承了
另外,想要继承函数内部的方法要格外小心,先看一个例子:
var x = function(){ var print = function() { console.log("I get it!"); } }; var y = function(){}; y.prototype = new x(); x.print(); //报错 (new x()).print(); //报错 (new y()).print(); //报错为什么会错呢,因为在函数内部通过var定义的方法或者直接定义的方法都是私有的,外界是访问不到的,也不能继承,换成
function print() { console.log("I get it!"); }也一样
再看另一个例子:
var x = function(){ this.print = function() { console.log("I get it!"); } }; var y = function(){}; y.prototype = new x(); x.print(); //报错 (new x()).print(); //I get it! (new y()).print(); //I get it!这里使用了this关键字,对于this关键字,以后会详细说明,这里只需要知道,new x()的时候,this指向了新创建的对象实例本身,然后对这个对象实例本身添加了一个print方法,机制和第一个例子一样,就是写法稍微不同而已
2.节省空间和提高效率
对一个对象添加方法,一个直接的写法是:
var x = function(){ this.print = function() { console.log("I get it!"); } }; (new x()).print(); //I get it!但一般不会这么写,而是这样写:
var x = function(){}; x.prototype.print = function() { console.log("I get it!"); }; (new x()).print(); //I get it!这样在创建对象x 的实例的时候,就不会重复地创建相应的方法和属性,所有通过new x()创建出来的对象实例都会继承x.prototype的方法和属性,比如这里创建出来的x对象实例都是空的,但是他们却能在需要的时候调用print()函数,所以,提高了运行效率(但是在不断搜寻原型链的时候也会耗费时间,所以原型链不宜过长)
PS:这里的几个例子都用了new 函数名()的方法来创建一个对象实例,其实这种方法在很多书上是不被推荐使用的,因为new方法只是JavaScript原型链继承机制向C类继承机制靠拢的一个手段,结果就是:It is the worst of both worlds
3.扩展原有的类库函数
由于JavaScript可以很方便地向一个对象添加方法,所以,我们可以对基本对象的原型添加方法,那么,所有继承这些基本对象的对象实例就将拥有这些方法
比如,我想给Number对象添加一个取整的方法:
Number.prototype.integer = function() { return Math[this < 0 ? 'ceiling' : 'floor'](this); };
之后就可以在所有的继承于Number对象的实例处使用这个方法了
console.log((10 / 3).integer()); //3
当然,扩展类库函数并不是特别推荐使用,因为有人说这样会破坏封装,而且还要特别注意函数是否已经被声明过,不过,这样写的确会简化某些操作
三. 一些很好的文章
1.浅析Javascript原型继承 这篇文章对JavaScript原型继承有一个很好的讲解
2.JavaScript秘密花园 这篇文章对JavaScript的语法机制有一个全面系统的讲解,十分推荐!
相关文章推荐
- javascript学习笔记(九)javascript中的原型(prototype)及原型链的继承方式
- javascript 对象及原型继承有关的属性:constructor、prototype、isPrototypeOf、instanceof、in 、hasOwnProperty 等等
- javascript prototype的深度探索不是原型继承那么简单第1/3页
- JavaScript使用prototype原型实现的封装继承多态示例
- javascript中的原型(prototype)及原型链的继承方式
- 面向对象的Javascript - 通过原型(Prototype)实现继承
- JavaScript _proto_、prototype原型、原型链、constructor构造器、类式继承、原型继承
- javascript中的原型(prototype)及原型链的继承方式
- 详解JavaScript中基于原型prototype的继承特性
- JavaScript高级之prototype原型继承
- Javascript原型与继承【prototype】
- javascript原型继承分析(prototype)(补充版)
- javascript原型继承分析(prototype)
- 从0开始学react netive:2.Javascript创建对象的方式_prototype原型的概念_原型继承
- JavaScript面向对象编程之prototype原型与继承
- javascript 对象及原型继承有关的属性:constructor、prototype、isPrototypeOf、instanceof、in 、hasOwnProperty 等等
- 史上最通俗易懂的关于JavaScript 的 prototype、原型继承、this指针的讲解
- javascript原型继承分析(prototype)
- JavaScript的原型链继承__propt__、prototype、constructor的理解、以及他们之间相互的关系。
- JavaScript 利用prototype原型实现封装继承多态