javascript的原型与继承(2)
这是上一篇的后续。
Javascript是一种基于对象的语言,遇到的所有东西几乎都是对象。如果我们想要把属性和方法封装成一个对象,应该怎么做呢:
假设我们把猫看成一个对象:
var Cat = {
name : ‘’,
color : ‘’
}
现在,我们需要根据这个原型对象来生成两个具体的实例对象。
var cat1 = {};//创建一个空对象
cat1.name = “大毛”;
cat1.color = “yellow”;
var cat2 = {};//创建一个空对象
cat2.name = “二毛”;
cat2.color = “white”;
这样也算是一种封装吧。但这样的写法显然是有些缺点。一个是,如果需要多生成实例,会很麻烦。第二就是,实例和原型之间,看不出有什么联系。
原始模式的改进
我们可以写一个代码,来改变代码重复的问题。
function Cat(name,color){
return {
name : name,
color : color
}
}
然后生成实例对象,就等于在调用函数。
var cat1 = Cat(“大毛”,’yellow’); var cat2 = Cat(“二毛”,”white”);
这种方法减少了代码量,但依然看不出原型和实例的关系。
构造函数模式
为了解决原型对象生成实例的问题。javascript提供了一个构造函数。
所谓构造函数,其实是一个普通函数。但是内部使用了this变量。对构造函数使用new运算符,就能生成实例。并且this会绑定到实例对象上。
function Cat(name,color){
this.name = name;
this.color = color;
}
var cat1 = new Cat(“大毛”,’yellow’);
var cat2 = Cat(“二毛”,”white”);
构造函数的实例和原型之间如何联系呢,实例会含有一个constructor属性,该属性指向实例的构造函数。
alert(cat1.constructor == Cat); //true alert(cat2.constructor == Cat); //true
构造函数的问题:
资源浪费,前面已经说过,这里就不叙述了。
引入prototype属性
前面已经介绍
构造函数的继承
比如,现在有一个 动物 对象的构造函数。
function Animal(){
this.species = “animals”;
}
还有一个 猫 对象的构造函数
function Cat(name,color){
this.name = name;
this.color = color;
}
那怎样使“猫”继承“动物”呢?
1. 构造函数绑定:
将父对象的构造函数绑定在子对象上。
function Cat(name,color){
Animal.apply(this,arguments);
this.name = name;
this.color = color;
}
var cat1 = new Cat(“kitty”,”white”);
console.log(cat1.species); //animals
原型继承
这种也是比较常用的方法,采用prototype属性。
如果“猫”的prototype对象,指向一个Animal的实例。那么所有“猫”的实例,就能继承Animal了。
//将Cat的prototype对象指向一个Animal的实例。 Cat.prototype = new Animal(); Cat.prototype.constructor = Cat; var cat1 = new Cat(“大毛”,”white”); console.log(cat1.species);
将Cat的prototype对象指向一个Animal的实例,将完全删除prototype对象原先的值,重新赋予了一个新值。
Cat1的constructor本来是应该指向Cat这个构造函数的。但是因为:
Cat.prototype = new Animal();
Cat的constructor被指向了Animal这个构造函数。这会导致继承链的错乱。因此我们需要手动的进行纠正。
Cat.prototype.constructor = Cat;
直接继承prototype
这种方法是对前面方法的改进。由于在Animal对象中,不变的属性都直接写入了Animal的prototype中。因此,也可以让Cat跳过Animal,直接继承Animal.prototype。
Cat.prototype = Animal.Prototype; Cat.prototype.constructor = Cat;
与前一种相比,这样可以不用建立Animal实例,相对来说可以节约资源。缺点也很明显:Cat.prototype现在和Animal的prototype都指向了同一个对象。那么任何对Cat.prototype的操作,都会影响到Animal.prototype。所以这个时候,Animal.prototype的constructor也被指向了Cat,这显然不是我们想要的。
利用空对象作为中介
var F = function(){}
F.prototype = Animal.prototype;
Cat.prototype = new F();
Cat.prototype.constructor = Cat;
F是空对象,几乎不占内存。这时,修改Cat.prototype.constructor,也不会影响到Animal的prototype对象。可以将上面的方法,封装成一个函数。
function extend(child,parent){
var F = function(){};
F.prototype = parent.prototype;
child.prototype = new F();
child.prototype.constructor = child;
}
extend(Cat,Animal);
var cat1 = new Cat(“大毛”,”white”);
拷贝继承
这种逻辑是比较容易理解的,就是将父类的属性一一的拷贝到子类的属性中.
function Animal(){};
Animal.prototype.species = “animal”;
function extend2(child,parent){
var p = parent.prototype;
var c = child.prototype;
for(var k in p){
c[k] = p[k];
}
}
然而这种方法的缺点也是很明显的,将父类和子类的prototype指向了同一个存储单元。对于那些引用值类型的属性来说。修改其中的任意一方,都会对另一方的属性造成影响。
非构造函数的继承
道爷曾经提出过一个object()函数,可以做到这一点。
function object(o){
function F(){}
F.prototype = o;
return new F();
}
这种方法 其实和空对象中介方法,是一个道理的。
javascript的原型与继承(2)的更多相关文章
- 【面试必备】javascript的原型和继承
原型.闭包.作用域等知识可以说是js中面试必考的东西,通过你理解的深度也就能衡量出你基本功是否扎实.今天来复习一下javascript的原型和继承,虽说是老生常谈的话题,但对于这些知识,自己亲手写一遍 ...
- 深入浅出JavaScript之原型链&继承
Javascript语言的继承机制,它没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(instanc ...
- javascript的原型和继承(1)
原型与继承是javascript中基础,重要而相对比较晦涩难解的内容.在图灵的网上看到一篇翻译过的文章,有参考了一些知名博客.我自己总结了几篇.通过这次的总结,感觉自己对原型和继承的认识又增加了很多, ...
- JavaScript的原型链继承__propt__、prototype、constructor的理解、以及他们之间相互的关系。
回想自己已经工作了有一段时间了,但是自己对JavaScript的原型链.和继承的理解能力没有到位,最近他们彻底的整理并且复习了一遍. 本案例中部分文案来自网络和书籍,如有侵权请联系我,我只是把我的理解 ...
- JavaScript 面向对象 原型(prototype) 继承
1.对象的概念:无需属性的集合,属性可以为数值,对象或函数,ECMAscript中没有类的概念,这点是javascript与其他面向对象(OO)语言不同的地方. //创建一个自定义对象 var per ...
- JavaScript基于原型的继承
在一个纯粹的原型模式中,我们会摒弃类,转而专注于对象,基于原型的继承相比基于类的继承的概念上更为简单 if( typeof Object.beget !== 'function') { Object. ...
- javascript高级:原型与继承
原型继承的本质就是一条原型链,对象会沿着这条链,访问链里的方法属性. 对象的__proto__属性就是用于访问它的原型链的上一层: 考虑以下对象: 1. 所有对象的原型: Object.prototy ...
- 🍓JavaScript 对象原型链继承的弊端 🍓
- javascript中继承(一)-----原型链继承的个人理解
[寒暄]好久没有更新博客了,说来话长,因为我下定决心要从一个后台程序员转为Front End,其间走过了一段漫长而艰辛的时光,今天跟大家分享下自己对javascript中原型链继承的理解. 总的说来, ...
随机推荐
- 飞凌OK6410开发板SDIO无线8189WIFI模块驱动移植
为什么要移植?开发板不是已经提供了无线驱动吗? 貌似是这样的..本来是好用的.加入自己第三方驱动后发现WIFI用不了...最后发现飞凌提供的内核里面没有8189芯片的代码...问售后他们说那边是好的. ...
- Zepto源码
// Zepto.js // (c) 2010-2016 Thomas Fuchs // Zepto.js may be freely distributed under the MIT licens ...
- python函数递归和生成器
一.什么是递归 如果函数包含了对其自身的调用,该函数就是递归的.递归做为一种算法在程序设计语言中广泛应用,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,递归策略只需少量的 ...
- css兼容问题集合
css兼容问题 兼容问题 1.文字本身的大小不兼容.同样是font-size:14px的宋体文字,在不同浏览器下占的空间是不一样的,ie下实际占高16px,下留白3px,ff下实际占高17px,上留白 ...
- ApexSql Log 2014.04.1133破解版&补丁
已上传最新的2016版本,请移步: http://www.cnblogs.com/gsyifan/p/ApexSql_Log_2016_Crack.html 状态不好,鬼使补差的跑到服务器上updat ...
- mongoDB 使用手册
1.基本操作db.AddUser(username,password) 添加用户db.auth(usrename,password) 设置数据库连接验证db.cloneDataBase(fromh ...
- 关于 this 和 prototype 的理解
1:this 的理解比较好的书是 <Javascript语言精粹> 平时我们全局写 var a = 1, 其实就是 window.a = 1; var f = function(){}, ...
- poj 2337 有向图输出欧拉路径
Catenyms Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 10186 Accepted: 2650 Descrip ...
- 济南学习D2T1__折纸带
他[问题描述]一张长度为n的纸带,我们可以从左至右编号为0 −n(纸带最左端标号为0) .现在有m次操作,每次将纸带沿着某个位置进行折叠,问所有操作之后纸带的长度是多少.[输入格式]第一行两个数字n, ...
- 使用MySql数据库, 浏览器接收返回数据报错SyntaxError: unterminated string literal
用php写了一个很简单的页面, 用来记录常用的oracle的关键字和各种函数, 以后用起来查一下方便, 原来是用java写了一个web项目, 但是用起来太麻烦, 真的不如php方便, 然后就把整理的内 ...