`

一篇关于javascript-prototype继承

 
阅读更多
1.最基本的用法 把ClassA的一个实例赋值给ClassB,
ClassB就继承了ClassA的所有属性。
代码入下:

<script type="text/javascript">

    function ClassA() {
        this.a = 'a';
    }

    function ClassB() {
        this.b = 'b';
    }

    ClassB.prototype = new ClassA();
    var objB = new ClassB();
    for (var p in objB)//输出为 "ba"
        document.write(p + "");

</script>


2.从原型继承理论的角度去考虑,
js的原型继承是引用原型,不是复制原型,
所以,修改原型会导致所有B的实例的变化。
代码如下:

<script>
    
    function ClassA() {
        this.a = 'a';
    }
    
    function ClassB() {
        this.b = 'b';
    }
    
    ClassB.prototype = new ClassA();
    var objB = new ClassB();
    alert(objB.a);//输出 "a"
    ClassB.prototype.a = 'changed!!';
    alert(objB.a);//output-> "changed"
    var c = new ClassB();
    alert(c.a);// output -> "changed"
    
</script>



3.然而 子类对象的写操作只访问子类对象中成员,
它们之间不会互相影响,因此,
写是写子类 读是读原型(如果子类中没有的话)。

<script>

    function ClassA() {
        this.a = 'a';
    }

    function ClassB() {
        this.b = 'b';
    }

    ClassB.prototype = new ClassA();
    var objB1 = new ClassB();
    var objB2 = new ClassB();
    objB1.a = '!!!';//修改新对象的属性并不会影响原型
    alert(objB1.a); //output -> "!!!"
    alert(objB2.a); //output -> "a"
    var newb = new ClassB();
    alert(newb.a);// output -> "a"


</script>


4.每个子类对象都执有同一个原型的引用,
所以子类对象中的原型成员实际是同一个。

<script>

    function ClassA() {
        this.a = function () {
            alert("a");
        };
    }

    function ClassB() {
        this.b = function () {
            alert("b");
        };
    }

    ClassB.prototype = new ClassA();
    var objB1 = new ClassB();
    var objB2 = new ClassB();
    alert(objB1.a == objB2.a);//在没有使用方法之前,被继承的方法都不会执行,所以这儿为true,注意 属性 和 对象 的方式是不一样的,如果是简单属性会立即创建,否则则是到了需要的时候才创建
    alert(objB1.b == objB2.b);//子类的方法在对象创建的时候已经分配空间,因为属于不同空间的两个方法,所以为 false

</script>




<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>

<script type="text/javascript">

    var lis = document.getElementsByTagName("li");
    for(var index=0;index<lis.length;index++) {
        lis[index].addEventListener("click",function(){
            this.className = index;
        });
    }

</script>

当点击每个li的时候,会添加一个class,结果为每次点击li他们的class都是5,这个就很好解释了方法在没有执行前是不会新建空间来保存的,只有等到事件触发了才会去创建空间来保存生成的数据,例子不太好,意思可以从代码中理解出来



5.构造子类时 原型的构造函数不会被执行

<script>
    
    function ClassA() {
        alert("a");
        this.a = function () {
            alert("inner a");
        };
    }
    
    function ClassB() {
        alert("b");
        this.b = function () {
            alert("innner b");
        };
    }
    
    ClassB.prototype = new ClassA();
    var objB1 = new ClassB();//不会alert
    var objB2 = new ClassB();//不会alert
    
</script>


6.接下来是致命的,在子类对象中访问原型的成员对象:

<script>

    function ClassA() {
        this.a = [];
    }
    
    function ClassB() {
        this.b = function () {
            alert("");
        };
    }
    
    ClassB.prototype = new ClassA();
    var objB1 = new ClassB();
    var objB2 = new ClassB();
    objB1.a.push(1, 2, 3);
    alert(objB2.a);//所有b的实例中的a成员全都变了!!  

</script>


7.所以 在prototype继承中 原型类中不能有成员对象! 所有成员必须是值类型数据(string也可以)
用prototype继承有执行效率高,不会浪费内存,为父类动态添置方法后子类中马上可见等的优点。

8.prototype继承是通过把子类的原型对象(prototype)设置成父类的一个实例来进行继承的。

9.prototype继承也有四个比较明显的缺点:
  缺点一:父类的构造函数不是像JAVA中那样在给子类进行实例化时执行的,而是在设置继承的时候执行的,并且只执行一次。这往往不是我们希望的,特别是父类的构造函数中有一些特殊操作的情况下。
  缺点二:由于父类的构造函数不是在子类进行实例化时执行,在父类的构造函数中设置的成员变量到了子类中就成了所有实例对象公有的公共变量。由于JavaScript中继承只发生在“获取”属性的值时,对于属性的值是String,Number和Boolean这些数据本身不能被修改的类型时没有什么影响。但是Array和Object类型就会有问题。
  缺点三:如果父类的构造函数需要参数,我们就没有办法了。
  缺点四:子类原本的原型对象被替换了,子类本身的constructor属性就没有了。在类的实例取它的constructor属性时,取得的是从父类中继承的constructor属性,从而constructor的值是父类而不是子类。

10.可以针对prototype的缺点进行改造
比如把它写成Function对象的一个方法,这样用的时候方便。

Function.prototype.Extends = function (parentClass) 
{ 
var Bs = new Function(); 
Bs.prototype = parentClass.prototype; 
this.prototype = new Bs(); 
this.prototype.Super = parentClass; 
this.prototype.constructor = this; 
} 




针对第3,6个

<script>
    function ClassA() {
        this.a = [];
        this.aa = 100;
    }

    function ClassB() {
        this.b = function () {
            return "classb"
        };
    }
    ClassB.prototype = new ClassA();
    var objB1 = new ClassB();
    var objB2 = new ClassB();
    objB1.a.push(1, 2, 3);
    objB1.aa = 10100;
    alert(objB2.a);//1,2,3  a是对象类型
    alert(objB2.aa);//100 aa 是基本数据类型

</script>


针对继承,
Array.prototype 就不能继承 ClassA,ClassB

<script>

    function ClassA() {
        this.a = [];
        this.aa = 100;
    }

    function ClassB() {
        this.b = function () {
            return "b"
        };
    }

    ClassB.prototype = new ClassA();
    Array.prototype = new ClassB();
    var _array = new Array();
    alert(_array.b());//[i]Uncaught TypeError: Object [object Array] has no method 'b' [/i]

</script>




利用 apply call 实现继承方法

<script type="text/javascript">
    function classA () {
        this.x = 1;
        this.y = 2;
    }

    function classB() {
        this.z = 3;
    }
    
    classB.prototype = new classA();
    var b = new classB();
    alert(b.x+ b.z);

</script>
分享到:
评论

相关推荐

    不错的一篇关于javascript-prototype继承

    在 JavaScript 中,可以通过将一个类的实例赋值给另一个类的 `prototype` 属性来实现继承。这种继承方式被称为**原型链继承**。 例如,在给定的示例中,`ClassB` 继承了 `ClassA` 的所有属性: ```javascript ...

    prototype学习笔记

    在JavaScript中,`prototype`是一个核心...总的来说,这篇"prototype学习笔记"深入讲解了JavaScript中的原型和继承机制,结合源码分析和实用工具,帮助开发者更全面地掌握这一核心概念,并能够在实际项目中灵活运用。

    JavaScript学习之三 — JavaScript实现继承的7种方式

    本篇文章将深入探讨JavaScript实现继承的七种常见方式,帮助你更好地理解和运用这一概念。 1. 原型链继承(Prototype Chain Inheritance) 原型链是JavaScript实现继承的基础。每个函数都有一个`prototype`属性,这...

    JavaScript实现继承的几种方式

    本篇文章将深入探讨JavaScript中实现继承的几种常见方式。 1. 原型链继承 JavaScript的原型(prototype)机制是实现继承的基础。每个函数都有一个prototype属性,这个属性指向一个对象,这个对象的属性和方法可以被...

    JavaScript-学习笔记.docx

    这篇学习笔记主要涉及了JavaScript的基础概念和一些高级特性,包括预编译、作用域、函数、对象原型、原型链、函数调用方式(如call、apply)、继承模式、对象克隆、数组操作、自定义类型判断以及错误处理机制。...

    prototype.js简介

    **描述:** prototype.js 是一个JavaScript库,主要目的是为了简化JavaScript的开发,提升开发效率。它通过扩展JavaScript的基本对象和类型,提供了丰富的功能,包括类式继承、面向对象编程的支持以及一些实用的DOM...

    【JavaScript源代码】一篇文章教你JS函数继承.docx

    在JavaScript中,函数继承是面向对象编程的一个核心概念,尤其在没有类的原生支持时显得尤为重要。本文将详细讲解JavaScript中的几种常见的函数继承方式,包括原型链继承、借用构造函数继承(对象伪装)、组合继承、...

    JavaScript 学习 - 提高篇

    每个函数都有一个 `prototype` 属性,这是一个预定义的对象,用于继承父类的属性和方法。 **扩展原型** ```javascript function Book(name, author, pages) { this.name = name; this.author = author; this....

    Prototype学习笔记(一)(二)

    在JavaScript中,Prototype是一个核心概念,它涉及到对象的继承机制。Prototype学习笔记(一)(二)涵盖了这一主题的深入探讨,旨在帮助开发者更好地理解和利用这个特性。在本篇文章中,我们将详细阐述Prototype的...

    javascript继承实例

    本篇文章将深入探讨JavaScript继承的实例,以及如何通过继承来提高代码的可维护性和效率。 首先,我们需要了解JavaScript中的原型(prototype)机制。每个JavaScript对象都有一个内部属性[[Prototype]],通常通过`_...

    Javascript - 全面理解 caller,callee,call,apply (转载)

    这篇文章将深入探讨四个关键概念:caller、callee、call和apply,它们都是JavaScript函数操作的核心部分,对于理解和使用高级JavaScript编程至关重要。 首先,我们来了解`caller`和`callee`。在JavaScript的函数...

    javascript 封装 继承

    在JavaScript中,封装和继承是面向对象编程的两个核心概念,它们使得代码更加模块化、可维护,并且能够实现代码重用。这篇文章将深入探讨这两个主题,并结合给出的标签“源码”和“工具”,来解释如何在实际开发中...

    编写javascript插件,来扩展已有的JavaScript功能.zip

    在压缩包的文件名中,"1.JavaScript String.prototype 原型 - 何鸿涛 - 博客园.url"可能指向一篇关于String.prototype的详细教程,这部分内容会涵盖JavaScript中如何使用和扩展原型链。了解和熟练掌握原型链对于编写...

    13、JavaScript继承实现(二) —— zInherit、xbObjects

    zInherit是一种常用的JavaScript继承实现方式,它通过修改对象的`__proto__`属性来实现继承。`__proto__`指向父对象的原型,从而使得子对象能够访问父对象的属性和方法。但是,`__proto__`并不是所有浏览器都支持的...

    JavaScript 继承详解 第一篇

    JavaScript中的每个对象都可以有自己的属性和方法,而且每个对象还关联一个原型对象(prototype),该原型对象又关联另一个原型对象,如此形成一个原型链(prototype chain)。当访问一个对象的属性或方法时,...

    prototype学习

    在JavaScript中,`prototype`是一个核心概念,它与对象继承和函数原型紧密相关。`prototype`机制是JavaScript实现面向对象编程的关键部分。本篇将深入探讨`prototype`的基本原理、用法以及它在实际开发中的应用。 #...

    java script 继承的实现

    1. **原型链继承**:这是最基础的继承方式,JavaScript 对象都有一个内部 `[[Prototype]]` 属性,通常通过 `__proto__` 或 `Object.getPrototypeOf` 访问。通过将一个对象设置为另一个对象的原型,子类就可以继承...

    Javascript面向对象编程.

    2. **原型(Prototype)**:JavaScript中的每个对象都有一个内置的`__proto__`属性,指向其构造函数的原型对象。原型对象可以包含共享的方法和属性,使得实例可以访问。我们也可以通过`prototype`属性来修改构造函数...

    JavaScript使用Prototype实现面向对象的方法

    虽然JavaScript本身并非一种典型的面向对象语言,但它提供了基于原型(Prototype)的面向对象机制,使得开发者能够实现类似面向对象的特性。在本篇中,我们将深入探讨如何使用`Prototype`属性来实现面向对象的方法。 ...

    JavaScript实用小函数(一)

    这篇博客"JavaScript实用小函数(一)"可能涵盖了JavaScript基础以及一些实用技巧,虽然具体细节未在描述中给出,但我们可以根据常见的话题进行深入探讨。本文将主要围绕JavaScript中的函数、面向对象编程以及多态性来...

Global site tag (gtag.js) - Google Analytics