《JavaScript高级程序设计》笔记——关于继承

继承在JavaScript中是一种“奇葩”的存在,因为其本身并没有类(class)的概念(ES5),所以只能用其他方式(原型链、构造函数、对象实例)来模拟继承的行为。既然是模拟,那就应该是想办法实现继承的行为特点,个人认为继承的核心就是:复用。

写在前面:

  方法是属性的特殊形式,这里就用属性全权代表。

函数构造器里的属性是实例属性,每个实例都有自己的一份,实例之间互不影响。

     原型对象里的属性为每个实例共享,一旦改变,所有实例的原型属性都改变。

  以下的父类(SuperType)和子类(SubType)都有自己的实例属性和原型属性,各自的构造函数就不重复了,只列出继承核心步骤以突出重点。

     1.原型链继承:

1 SubType.prototype = new SuperType();

特点:父类的所有属性(包括实例属性和原型属性)都作为了子类的原型属性。

说明:纳尼?!一下都弄到原型属性里这样合适么,你考虑过实例属性的感受么?在父级既然是每个实例独享一份,到了子类却变成共享的了,这样使用限制很大哟!

     2.借用构造函数继承:

克服原型链的不足:实例属性用构造器继承。

1 function SubType(){
2   SuperType.call(this);
3 }

特点:父类的实例属性在子类还是实例属性,每个实例独一份互不干扰;另外,还可以利用call方法的特性给父类的构造函数传递参数。

说明:原型链的问题克服了,复用呢?父类的原型属性根本就没有在子类中体现啊!这样也没法用呢。

     3.组合继承:

综合一下前两种继承的优点吧,上帝的归上帝,凯撒的归凯撒。

function SubType(){
    //继承实例属性
    SuperType.call(this);
}
//继承原型属性
SubType.prototype = new SuperType();

特点:这样比较完美了,父类的实例属性在子类中单独继承,原型属性也有了复用的特点;并且保留了传参数的优点。

说明:但是处女座的朋友会发现,这关键的两步都调用了父类的构造函数,直接结果就是子类继承父类的实例属性会存在两份,一份在原型对象中,一份在子类实例中,只不过原型属性被实例属性覆盖罢了。这是多么可耻的浪费啊!

     4.寄生组合式继承:

请先不要问我“寄生”是什么意思~~组合继承的“浪费”主要是在原型链继承的过程中发生的,所以我们现在不借助父级实例重写子类原型对象,单独给子类一个只包括父类原型对象属性的对象即可。

首先来个用于复制父类原型对象的工具函数:

 1 function copy(uber){
 2   var F = function(){};
 3   F.prototype = uber;
 4   return new F();
 5 }
 6 //继承实例属性
 7 function SubType(){
 8   SuperType.call(this);
 9 }
10 //继承原型属性
11 SubType.prototype = copy(SubType.prototype);
12 SubType.prototype.constructor = SubType;  //不要忘记修正constructor   

特点:完美实现了继承,而且没有浪费内存空间,还能传参;就是写起来有点儿麻烦

     5.原型式继承

好吧回过头来说一下这个寄生,在讲寄生前允许我啰嗦一下“原型式继承”:

1 function copy(obj){
2     var F = function(){};
3     F.prototype = obj;
4     return new F();
5 }

特点:这种继承基于实例,只需给一个父类的实例对象就“还”一个子类实例对象,直接绕过构造函数,很简单吧。

说明:与其说是继承,其实这种方式更像是一种对象的“浅复制”,而且还有两个缺陷:1.不同子对象之间根本就没有函数的复用,2.由于是浅复制不同子对象之间会共用对象类型的属性,不能随意改动。但作者尼古拉斯说是,那就是吧。

     6.寄生式继承

寄生式继承是对原型式继承的一种加强:

1 function createAnother(original){
2     var clone = object(original);     //不一定必须用object方法,基于original复制新创建的即可
3     clone.sayHi = funciton(){  ……   }     // 增强
4     return clone;
5 }

特点:这里返回的clone不仅有original的所有属性,还有自己的方法。

说明:寄生组合式继承的两个缺陷没有修复,所以我觉得这个继承方式依然很牵强;个人感觉“寄生”的由来就是将自己sayHi放在了original上面,额……回到第四种继承方式,我想体现寄生的地方就在于SubType.prototype.constructor = SubType(个人观点)

总结:最常用的继承方式应该是组合式继承  和  寄生组合式继承

以上是基于JS红宝书6.3继承章节的一些读书心得,欢迎吐槽。

时间: 2024-12-04 12:02:17

《JavaScript高级程序设计》笔记——关于继承的相关文章

javascript高级程序设计——笔记

javascript高级程序设计--笔记 基本概念 基本数据类型包括Undefined/Null/Boolean/Number和String 无须指定函数的返回值,实际上,未指定返回值的函数返回的是一个特殊的undefined值 变量.作用域和内存问题 基本类型值在内存中占据固定大小的空间,因此保存在栈内存中 引用类型的值是对象,保存在堆内存中 确定一个值是哪种基本类型用typeof,确定一个值是哪种引用用instanceof 所有变量都存在于一个执行环境当中,这个执行环境决定了变量的生命周期,

javascript高级程序设计笔记1

最近在看javascript高级程序设计,看之前觉得自己的js学得还不错,然后,看了没几页就觉得自己好像没有学过一样,这主要写写我以前不完全了解的一些知识. 首先是关于基本数据类型的,从Number开始,以前经常用parseInt来转换数值,看过书才知道,这个函数的本意是专门用于把字符串转换成数值,而且以前也不知道它具体是怎么一个转换规则.先来看看Number()函数的转换规则: 1.如果是Boolean 值,true 和false 将分别被转换为1 和0.2.如果是数字值,只是简单的传入和返回

JavaScript高级程序设计笔记之面向对象

说起面向对象,大部分程序员首先会想到 类 .通过类可以创建许多具有共同属性以及方法的实例或者说对象.但是JavaScript并没有类的概念,而且在JavaScript中几乎一切皆对象,问题来了,JavaScript中如何面向对象? JavaScript中将对象定义为:一组无序的 键值对的集合,属性以及方法的名称就是键,键的值可以是任何类型(字符串,数字,函数--) 在JavaScript中,所有对象继承自Object,所有对象继承自Object,所有对象继承自Object! 创建 1  简单创建

Javascript高级程序设计笔记(很重要尤其是对象的设计模式与继承)

var obj = {'a':'a'}; var fun = function (){} console.log(typeof obj);//object console.log(typeof fun);//function var a; console.log(a === undefined);//true console.log(typeof b);//true 未声明的变量使用会报错,但是他的typeof=undefined var c=null; console.log(typeof c

javascript高级程序设计笔记(第5章 引用类型)

1.Object类型 两种方式定义:对象字面量.new 两种方式访问:括号.点 2.Array类型 2.1  定义方式:new Array.数组字面量 2.2  lenght属性:可以利用它方便的想数组末尾添加元素 2.3  检测数组 instanceof isArray()方法  2.4  toString().soLocaleString().valueOf().join()方法 2.5.栈方法   push()方法:逐个添加到数组末尾,并返回修改后的数组长度 pop()方法:返回数组的最后

【javascript高级程序设计笔记】第六章OOP

忙了一段时间,加了将近一个月的班. 书也落下没看,上次看到第七章(这部分笔记大概还是9月份的吧),偶尔看到很吃力.看的速度慢下来. 学习就是一个慢慢积累慢慢沉淀的过程.看书时没有明显觉得提升.但在看完书后近段时间工作中写代码,明显感觉效率还是有提升,基础知识牢固了. 这本书是第二次看,这次很认真的遍读和做笔记,笔记的文字均是自己边看边敲的,这样才更好的真正的吸收到一部分吧! 这些天在看web响应式设计:HTML5和CSS3实战 第6章 面向对像的程序设计 6.1.1属性类型 ECMAScript

JavaScript高级程序设计笔记(一)

1. ECMA规定了这门语言的下列组成部分: 语法. 类型.语句. 关键字.保留字.操作符. 对象 2. 什么是 ECMAScript 兼容支持 ECMA描述的所有"类型.值.对象.属性.函数以及程序句法和语义"支持 Unicode 字符标准. 此外,兼容的实现还可以进行下列扩展.添加 ECMA没有描述的"更多类型.值.对象.属性和函数".支持 ECMA没有定义的"程序和正则表达式语法". 3. 5种简单数据类型: Undefined(不明确的,

javascript高级程序设计笔记(第7章 函数表达式)

7.5 小结 在JavaScript 编程中,函数表达式是一种非常有用的技术.使用函数表达式可以无须对函数命名,从而实现动态编程.匿名函数,也称为拉姆达函数,是一种使用JavaScript 函数的强大方式.以下总结了函数表达式的特点.? 函数表达式不同于函数声明.函数声明要求有名字,但函数表达式不需要.没有名字的函数表达式也叫做匿名函数.? 在无法确定如何引用函数的情况下,递归函数就会变得比较复杂:? 递归函数应该始终使用arguments.callee 来递归地调用自身,不要使用函数名——函数

【javascript高级程序设计笔记】第一章与第三章

第1章 javascript简介 1.2Javascript实现 一个完整的javascript实现由下列三个不同的部分组成 核心(ECMAScript) 提供核心语言功能 文档对象模型(DOM) 提供访问和操作网页内容的方法和接口 浏览器对象模型(BOM)提供与浏览器交互的方法和接口 ECMAScript 它规定了这门语言的下列组成部分: 语法  类型  语句  关键字 保留字 操作符 对象 ECMA-262第5版,发布于2009年. 文档对象模型(DOM) Document Object M

JavaScript高级程序设计笔记

1.1 JavaScript简史 <script> async/defer可以控制js加载顺序 把js文件放在页面底部,加快页面打开速度 3 基本概念 语法 数据类型 流控制语句 理解函数 3.4 数据类型 ECMAScript中定义了六种数据类型:Underfined.Null.Boolean.Number.String.Object 使用typeof关键字来检测类型 //Boolean()转换 var bool1 = Boolean(true); var bool2 = Boolean(&