原型模式的不足和解决办法

原型模式的缺点:
* 虽然省略了为构造函数传递初始化参数这一环节,结果所有的实例都有了默认的相同的属性值。会带来一些不方便,但主要问题还是由其共享的本质所导致的。
* 原型中所有的属性是被很多实例共享的,这对于函数非常舒服,但对于包含引用类型的属性来说,问题就出来了:

function Person() {
    }

    Person.prototype = {
        name: "Hongbin",
        age: 21,
        friends: ["A", "B"],
        satFriend: function () {
            console.log("my friends: "+this.friends);
        }
    };

    var person1 = new Person();
    var person2 = new Person();

    person1.friends.push("C");
 	console.log(person1);//["A","B","C"]

    console.log(person2);//["A","B","C"]

在这里插入图片描述
person1 用push()方法给friends属性添加一个字符串,但person2的friends也跟着改变了
问题:共享属性,一个实例按照自己想要实现的功能改变了属性的值,与其共享属性的实例对应属性的值也随之发生改变。
原因:person1实例中没有friends属性,向上找,找到了Person中的friends属性,改变了它,共享的person2也随之影响。

//解决办法 :******组合使用构造函数模式与原型模式********
//这是创建自定义类型的最常见方式。
//构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。这样每个实例都会自己的一份实例属性的副本,同时又共享着对方法的引用,最大限度的节省了内存。还有,这种模式还支持向构造函数传递参数;可谓集两家之所长。

在这里插入图片描述

function Person(name,age,sex) {
        this.name = name;
        this.age = age;
        this.sex = sex;
        this.friends = ["A","B"];
    }

    Person.prototype = {
        constructor : Person,
        sayHello:function () {
            console.log("Hi!"+this.friends);
        }
    };

    var person1 = new Person("Hongbin",21,true);
    var person2 = new Person("xiaomei",20,false);

    person1.friends.push("C");
    console.log(person1);//Person {name: "Hongbin", age: 21, sex: true, friends: Array(3)}
    console.log(person2);//Person {name: "Hongbin", age: 21, sex: true, friends: Array(2)}
	console.log(person1.friends == person2.friends);//false
    console.log(person1.constructor == person2.constructor);//true
    console.log(person1.sayHello == person2.sayHello);//true
发布了44 篇原创文章 · 获赞 58 · 访问量 8066

猜你喜欢

转载自blog.csdn.net/printf_hello/article/details/104252620