`

prototype 与 继承

 
阅读更多

继承与模仿:
    当我们定义好某个类时,将当前类的 prototype 属性指向某个类的对象就可以继承
    该类的所有公有属性方法了。
    当我们继承了某个类的方法后,在定义当前类的方法时可以使用 this.xxx 直接访问
    父类的方法。
    如果进行方法重写,在重写的方法中不能再使用父类的同一个方法,但这在java中
    可以通过 super 关键字类访问。在javascript中是否可以这样呢?如果有哪位大虾
    知晓的话,忘不吝赐教。

MyClass.prototype = new FatherClass(); // 将当前类的原型指向父类的对象 即可实现继承

 

    其实更明确的说这种关系类似于 “模仿” 而不是真正的继承,继承要求两个类具有 血缘关系 。
    在java中,子类继承了父类,那么他就拥有了父类的所有公有的方法和属性,他们具有了很近的
    血缘关系,而在javascript当中,通常说的是类模仿了某个类而拥有了被模仿类的公有属性和
    方法。
   
    模仿 不要求这两个东西是同一个类型的,而继承就规定了 他们两个必须是同一个类型的。
    笔记本电脑 是 电脑,台式电脑 是 电脑。他们都属于 电脑 这个大类。
    笔记本电脑 模仿了 笔记本造型,台式电脑 模仿了 电视造型。 他们之间没有必然的血缘关系。
    在javascript中,这个 prototype 就是来描述 模仿 这个关系。所以在javascript中严格的来
    将 是没有 “继承” 的。

    原型必须指定一个对象,在javascript中,每个对象的原型默认都是一个 Object 对象,注意是
    对象而不是 Object 类型。
    每个类有且仅有一个 原型,类间的继承关系有原型链决定。
   
    摘自:《javascript王者归来》
        “在现实生活中,我们常常说,某个东西是以另一个东西为原型制作的。这个两个东西可以是
        同一个类型的,也可以是不同的类型的。习语‘照猫画虎’,这里猫就是原型,而虎就是类型,
        用javascript的prototype来描述就是  虎.prototype=某只猫 或 虎.prototype=new 猫()”
       
        "'原型'是描述自然界事物之间‘归类’关系的一种,另外几种关系包括‘继承’和‘接口’。一般
        来说,‘继承’描述的是事物之间存在的固有的衍生关系,能被继承的事物具有很强的相关性。
        ‘接口’描述的是事物公用方面的共同特征。而‘原型’则倾向于描述事物之间的‘相似性’。从这
        一点来看,‘原型’在描述事物的关联性的方面,比继承和接口的意义更广。
            如果你是java程序员,上面的例子从继承的角度去考虑,当然不能让‘猫’去继承‘虎’,也
        不能让‘虎’去继承‘猫’,要描述它们之间的关系,我们需要建立一个涵盖了它们共性的‘抽象类’
        ,或者你会叫它‘猫科动物’ 。可是,如果系统中我们只需要用到‘猫’和‘虎’,那么这个多余的
        ‘猫科动物’对于我们来说没有任何意义,我们只是想表达 ‘虎’ 有点像 ‘猫’ 而已。在这里,
        用原型帮我们节省了一个没有必要建立的‘猫科动物’。"
   
    例子:

/*******************************************************************************
        * 类型: Human     人(父类)
        * 属性: name      省份
        *        age          年龄
        *        gender      性别
        *        addr      地址
        * 类属性: version 版本
        * 方法: getInfo   获取人的简单信息 返回类型:String
        ******************************************************************************
        */
        function Human(){}

        // 动态属性
        Human.prototype.name = "";
        Human.prototype.age = 0;
        Human.prototype.gender = "male";
        Human.prototype.addr = "null";

        // 动态方法
        Human.prototype.getInfo = function()
        {
            return info = "<h1>"
                + this.name + "</br>"   
                + this.age + "</br>"
                + this.gender + "</br>" 
                + this.addr + "</br>" 
                + "</h1>";
        }

        Human.version = 1;
       
       
        /*******************************************************************************
        * 类型: Student       学生
        * 属性: className     班级
        *        grade          年纪
        *        school          学校
        * 方法: getStuInfo    获取学生的简单信息 返回类型:String
        ******************************************************************************
        */
        function Student(){}

        Student.prototype = new Human();
        Student.prototype.className = "";
        Student.prototype.grade = 0;
        Student.prototype.school = "";

        Student.prototype.getStuInfo = function()
        {
            return this.getInfo()  // Human 中的方法
                    + "<h2>"
                    + this.school + "</br>"  // Student 中的属性
                    + "</h2>";
        }
        // /////////////////////////////////////////////////////////////////////////////

        var stu = new Student();
        stu.name = "小明";  // 父类中的属性
        stu.age = 8;  // 父类中的属性
        stu.addr = "北京";  // 父类中的属性

        stu.school = "朝阳小学"; // 子类中的属性

        document.write( stu.getInfo() );    // 父类中的方法 
        document.write( stu.getStuInfo() ); // 子类中的方法
       
        // /////////////////////////////////////////////////////////////
        // 定义第三方类 继承 Student
        function Test(){}
        Test.prototype = new Student(); // 继承 Student
       
        // Test 继承 Student 继承 Human 继承 Object
        var tt = new Test();
        document.writeln(tt instanceof Object); // true 每个类都默认继承自 Object
        document.writeln(tt instanceof Human); // true
        document.writeln(tt instanceof Student); // true
        document.writeln(tt instanceof Test); // true
        document.writeln(tt instanceof Date); // false
       
        document.writeln("</BR>");
       
        // 打印 Test 的所有属性和方法
        for (var each in tt)
        {
            document.writeln(each);
            // className grade school getStuInfo name age addr getInfo gender
        }

 


使用prototype:
        对象的原型属性或方法是对象共有的,如果对某个对象的原型进行操作,那么该类的其他对象
    都具有相同的属性。
        在访问对象的原型属性时不需要加prototype关键字,直接用点运算符进行访问和赋值。
    给对象的属性赋值时,新的值会覆盖原型中的值。之后我们可以用 delete(obj.property) 来删除
    某个属性,这时访问该属性的值时就是属性原型的值了。
        对象的原型属性值可以看做是属性的默认值,在没有给该属性赋值或删除该属性值的情况下,
    对象的属性值保持 默认值 。
   
    例子:

function Human(){}

        Human.prototype.name = "No name";
        Human.prototype.age = 0;
        Human.prototype.gender = "male";

        Human.prototype.getInfo = function()
        {
            return this.name + "</br>"
                   + this.age + "</br>"   
                   + this.gender + "</br>";
        }

        // //////////////////////////////////////////////////

        var man1 = new Human();
        man1.name = "熊猫";
        man1.age = 5;
        man1.gender = "famale";

        var man2 = new Human();

        // 每个对象都有 name age gend 属性
        document.writeln(man1.getInfo()); 
        document.writeln(man2.getInfo());

        document.writeln(man1.name); // 熊猫
        document.writeln(man2.name); // 默认值 “No name”

        delete(man1.name);    // 删除属性的值
        document.writeln(man1.name); // 恢复 默认值 “No Name”
   
只读的getter
    /*******************************************************************************
     * 类型:     Address  地址
     * 属性信息: province 省份
     *           city     城市
     * 方法:     toString 覆盖Object类中的 toString
     ******************************************************************************
    */
    function Address(){}
    Address.prototype.province = "";
    Address.prototype.city = "";
    // 覆盖Object类中的 toString 方法
    Address.prototype.toString = function()
    {
        return this.province + "省" + this.city + "市</BR>";
    }
   
    /*******************************************************************************
     * 类型: Human        人
     * 属性: name         姓名
     *       addr         地址
     * 方法: getAddr      返回地址信息
     *       getAddress   返回地址信息  只读方法,不可以通过返回的地址改变地址的内容
     ******************************************************************************
    */
    function Human(name, addr)
    {
        this.name = name;
        this.addr = addr;

        this.getAddr = function()
        {
            return this.addr;
        }
        this.getAddress = function()
        {
            function Tmp(){}
            Tmp.prototype = this.addr;
            return new Tmp();
        }
    }
    // /////////////////////////////////////////////
    var add = new Address();
    add.province = "陕西";
    add.city = "西安";

    var man = new Human("熊猫", add);
    document.writeln( man.getAddr() ); // 陕西省西安市
   
    // 通过 getAddr 方法获得地址属性并改变它
    var temp1 = man.getAddr();
    temp1.province = "湖南";
    document.writeln( man.getAddr() ); // 湖南省西安市  已修改

    // 通过 getAddress 方法获得地址属性并改变它
    var temp2 = man.getAddress();     
    temp2.province = "湖北";
    document.writeln( man.getAddr() ); // 湖南省西安市  未修改

 

 

 

 

prototype 特性:
    1.通过 prototype 定义的属性是所有对象共有的,且这个属性的值是只读的。对象只能通过覆盖
        该属性的值,当对象的特定属性没有赋值时,它的值就是定义prototype时的原始值。
       
    2.尽量通过prototype来定义类的属性和一些方法,除非需要用到闭包来封装某些私有属性时。
        直接在类的定义中通过 this.xxx 定义方法或属性的话,在每一个new对象的时候都会对
        这些属性或方法进行初始化,这样不仅降低了效率而且还有初始值被覆盖的风险。
       
    3.通过制定类型的prototype,可以模拟继承。
   
    4.可以以任何一个对象为原型,安全的建立大量的实例。

 var p = "asdfasd";
        var pp = function(){};
        pp.prototype = p;
        var pps = [];
       
        for (var i = 0; i < 10000; i ++)
        {
            pps[i] = new pp(); // 创建大量的p 的副本。clone对象。
            // 由于pp构造方法是个空的,所以比直接构造 p 对象要快的多。
        }

 

       
    5.类的继承链是有 prototype 构成的,这个继承链当中如果有一个 prototype 的值发生改变,
        将传递性的影响这个链接下方的所有对象。且如果其中有一个 prototype 的值是一个引用
        (比如数组),那么任何一个对该引用的操作都会影响且改变其它对象中该属性的值。

分享到:
评论

相关推荐

    Javascript中的prototype与继承

    JavaScript中的prototype与继承是该语言面向对象编程的核心概念之一。prototype是JavaScript中实现原型继承的基础,它允许一个对象从另一个对象上继承属性和方法。通过了解prototype与继承的工作机制,开发者能够...

    深入了解javascript中的prototype与继承

    在JavaScript中,Prototype和继承是两个非常核心的概念,它们构成了JavaScript面向对象编程的基础。 Prototype是JavaScript实现继承的主要机制,而继承则是对象之间共享属性和方法的方式。本文将深入探讨这两个概念...

    js遍历属性 以及 js prototype 和继承

    3. `Object.getOwnPropertyNames()`:与`Object.keys()`类似,但不会返回继承的属性。 ```javascript let ownKeys = Object.getOwnPropertyNames(obj); ownKeys.forEach(key =&gt; console.log(key + ": " + obj[key...

    JavaScript中prototype的使用

    2. **prototype与继承** 上述提到的“类型”和“原型”的关系是JavaScript继承的基础。通过设置一个对象的`prototype`为另一个对象,我们可以让这个对象继承另一个对象的属性和方法。例如,如果我们有一个`Point`...

    javascript中类和继承(代码示例+prototype.js)

    本文将深入探讨JavaScript中的类和继承,并结合`prototype.js`文件中的示例进行解析。 ### 类的概念与模拟 在JavaScript中,我们通常使用函数来模拟类的行为。一个函数可以看作是一个类的定义,通过`new`关键字来...

    Javascript学习笔记9 prototype封装继承

    ### prototype与继承的关系 在JavaScript中,每个对象都有一个原型(prototype),原型本身也是一个对象。当尝试访问一个对象的属性时,如果对象本身不存在该属性,则会在其原型链上查找该属性。JavaScript利用原型...

    javascript的prototype继承

    6. **效率与内存管理**:由于原型继承是基于原型链的,它通常比基于类的继承更高效,因为它不会为每个子类实例创建额外的副本。同时,通过在运行时添加方法,可以动态地扩展父类,这些方法对子类立即可见。 7. **...

    详解JavaScript中基于原型prototype的继承特性_.docx

    JavaScript中的原型(prototype)机制是实现继承的一种核心方式。由于JavaScript是一种基于原型的面向对象语言,它不支持传统的类(class)概念,因此其继承机制显得与众不同。在JavaScript中,对象可以直接从另一个...

    构造函数定义对象+prototype继承的实现.html

    构造函数定义对象+prototype继承的实现,含CSS样式

    prototype学习笔记

    其次,`__proto__`和`Object.prototype`也与`prototype`密切相关。`__proto__`是对象内部的一个引用,它指向创建该对象的构造函数的`prototype`。而`Object.prototype`是最基础的原型对象,所有其他对象都直接或间接...

    Prototype-1.6.0 中文版\英文版\Prototype.js

    1. **类与对象继承**:Prototype.js引入了基于原型的类系统,允许开发者创建类并实现继承。这使得JavaScript代码可以采用面向对象的方式编写,增强了代码的可读性和可维护性。 2. **DOM操作**:Prototype提供了强大...

    JavaScript不使用prototype和new实现继承机制

    传统的继承方法是通过原型链(prototype chain)实现的,这通常涉及到对prototype对象的操作以及使用new关键字来创建新对象。然而,这种方法有时会显得复杂且代码可读性不强,同时可能会导致原型链污染的问题。本文...

    JavaScript使用prototype属性实现继承操作示例

    主要介绍了JavaScript使用prototype属性实现继承操作,结合实例形式详细分析了JavaScript使用prototype属性实现继承的相关原理、实现方法与操作注意事项,需要的朋友可以参考下

    prototype_PrototypeJS1.6_

    标题"prototype_PrototypeJS1.6_"中提到的"Prototype"是一个JavaScript库,它为JavaScript编程提供了一套丰富的工具集,主要用于简化DOM操作、创建Ajax应用以及实现对象的继承机制。"1.6版本"表明这是该库的一个特定...

    prototype_1.7.3.js 最新版本

    它与流行的库如jQuery和Dojo相比,虽然在市场份额上可能略显逊色,但在某些特定场景下,如需要强大的面向对象特性时,Prototype.js仍然是一个理想的选择。 总之,Prototype_1.7.3.js以其丰富的功能、高效的性能和对...

    JavaScript的prototype

    JavaScript中的`prototype`是一个核心概念,它涉及到对象继承和函数原型。在JavaScript中,每创建一个函数,该函数就会自动获得一个名为`prototype`的属性,这个属性是一个对象,用于实现对象间的继承。同时,每个...

    prototype

    JavaScript是一种基于对象和原型的动态类型语言,它的对象继承机制是通过原型链(Prototype Chain)来实现的。在JavaScript中,每个对象都有一个内置的`__proto__`属性,这个属性指向了创建该对象的构造函数的原型。...

    ajax培训.AJAX 的入门知识

    ### Prototype与继承 JavaScript中的原型(Prototype)机制允许对象间共享属性和方法,从而节省内存。通过`class.prototype`可以添加或修改对象的属性和方法。反射机制(如`for...in`循环)可以遍历对象的所有属性...

Global site tag (gtag.js) - Google Analytics