• JavaScript 原型链学习(三)原型对象存在的问题 与 组合使用构造函数和原型


    原型对象也不是没有缺点。首先,它省略了为构造函数传递初始化参数这一环节, 结果所有实例在默认情况下都将取得相同的属性值。虽然这会在某种程度上带来一些不方便, 但还不是原型对象的最大问题。原型对象的最大问题是由其共享的本性所导致的。
    原型中所有属性是被很多实例共享,这种共享对于函数非常合适。对于那些包含基本值的属性倒也说得过去,毕竟(如前面的例子所示),通过在实例上添加个同名属性, 可以隐藏原型中的对应属性。然而,对于包含引用类型值的属性来说,问题就比较突出了。来看下面的例子。 

    function Person() {}
    
    Person.prototype={
        constructor: Person,
        name : "Nicholas" ,
        age : 29,
        job : "Software Engineer",
        friends : ["Shelby", "Court"] ,
        sayName : function (){
            alert(this.name ) ;
        }
    };
    
    var person1 = new Person();
    var person2 = new Person();
    
    person1.friends.push("Van");
    
    alert(person1.friends);    //”Shelby, Court, Van"
    alert(person2.friends);    //”Shelby, Court, Van"
    alert(person1.friends === person2.friends);     //true    

    在此,Person.prototype对象有一个名为frends的属性,该属性包含一个字符串数组。然后,创建了Person的两个实例。接着修改了person1.friends引用的数组,向数组中添加了一个字符串。由于friends数组存在于Person.prototype而非person1中,所以刚刚的修改也会通过person2.friends(与person1.friends指向同一个数组)反应出来。假如我们的初衷就是像这样在所有实例中共享一个数组,那就没什么好说的。可是,实例一般都是要有属于自己的全部属性的。而这个问题正是我们很少看到有人单独使用原型的原因。

    创建自定义类型的最常见方式,就是组合使用构造函数与原型。构造函数用于定义实例属性,而原型用于定义方法和共享的属性。结果,每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。下面的代码重写了前面的例子。

    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.friends = ["Shelby","Court"];
    }
    
    Person.prototype = {
        constructor : Person,
        sayName : function() {
            alert(this.name);
        }
    }
    
    var person1 = new Person("Nicholas", 29,"Software Engineer");
    var person2 = new Person("Greg", 27, "Doctor");
    
    person1.friends.push ("Van");
    alert(person1.friends);    //"Shelby, Count ,Van"
    alert(person2.friends);    //"She1 by,Count"
    alert(person1.friends === person2.friends);    //false
    alert(person1.sayName === person2.sayName);    //true

    在这个例子中,实例属性都是在构造函数中定义的,而由所有实例共享的属性constructor和方法sayName()则是在原型中定义的。而修改了person1.friends (向其中添加一个新字符串),并不会影响到person2.friends,因为它们分别引用了不同的数组。
    这种构造函数与原型混成的模式,是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。

  • 相关阅读:
    讲述Sagit.Framework解决:双向引用导致的IOS内存泄漏(上)
    Sagit.Framework For IOS 开发框架入门教程4:注册页布局-被消灭的变量
    Sagit.Framework For IOS 开发框架入门教程3:Start引导页及框架布局和隐藏事件的内幕
    Sagit.Framework For IOS 开发框架入门开发教程2:一行代码实现引导页
    Sagit.Framework For IOS 开发框架入门开发教程1:框架下载与环境配置
    CYQ.Data 正式支持 DotNET Core 版本发布
    IT连创业系列:App产品上线后,运营怎么搞?(中)
    IT连创业系列:App产品上线后,运营怎么搞?(上)
    分享:苹果APP更新上架被拒的另一种理由(Safety
    IT连创业系列:说说苹果商店AppStore上架App应用前后遇到的那些神坑
  • 原文地址:https://www.cnblogs.com/weiyalin/p/9416582.html
Copyright © 2020-2023  润新知