JS红宝书之创建对象的多种方式

借鉴了github里冴羽大佬的笔记,让我在读红宝书的时候通畅很多。地址:https://github.com/mqyqingfeng/Blog

虽然Object构造函数或对象字面量可以用来创建单个对象,但使用同一个接口创建很多对象,会产生大量的重复代码。

6.2.1 工厂模式

function createPerson (name,age){
    
    
    var o = new Object();
    o.name = name;
    o.age = age;
    o.getName = function() {
    
    
        console.log(this.name)
    }
    return o;
}
var person1 = createPerson("Pinocchio",14)

他虽然解决了创建很多相似对象的问题,但却没有解决对象识别问题,因为所有实例都指向一个原型。

6.2.2 构造函数模式

function Person(name,age){
    
    
    this.name = name;
    this.age = age;
    this.getName = function(){
    
    console.log(this.name);}
}
var person1 = new Person("Pinocchio",14)

**优点:**每个实例可以识别为一个特定的类型。 缺点:每次创建实例时,每个方法都要被创建一次。

这种方式会经历以下四个步骤:

  • 刻在堆内存中创建一个新的对象
  • 将构造函数的作用域赋给新对象(因此this指向这个新对象)
  • 执行构造函数中的代码(为这个新对象添加属性)
  • 将新建的对象作为返回值

alert(person1 instanceof Object); //true 所有对象都是Object实例,同时person1也是Person的实例

6.2.3 构造函数模式的优化

function Person(name,age){
    
    
    this.name = name;
    this.age = age;
    this.getName = getName
}
function getName(){
    
    
    console.log(this.name)
}
var person1 = new Person("Pinocchio",14)

**优点:**解决了每个方法都要被重新创建的问题。 **缺点:**这就没有封装的效果了。别的人也可以用getName函数。

6.2.4 原型模式

每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象。

function Person(){
    
    
    Person.prototype.name = "Pinocchio";
    Person.prototype.age = 14;
    Person.prototype.getName = function(){
    
    console.log(this.name);}
}
var person1 = new Person();
var person2 = new Person();
alert(person1.getName == person2.getName);   //true

**优点:**方法不会被重新创建 。 **缺点:**所有属性和方法都共享,无法初始化参数。比如原型中有一个引用类型,那么一个实例属性的改变会导致另一个实例属性也发生改变。

6.2.5 组合模式:使用构造函数+原型模式

构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性。

function Person(name,age){
    
    
    this.name = name;
    this.age = age;
    this.friends = ['li','wang'];
}
Person.prototype = {
    
    
    constructor:Person;
    sayName(){
    
    
        alert(this.name)
    }
}
var person1 = new Person('dsa',23)

**优点:**该共享的共享,该私有的私有,使用最广泛的方式。

**缺点:**没有写在一起,即更好的封装性

6.2.6 动态原型模式

function Person(name,age){
    
    
	this.name = name;
    this.age = age;
    if(typeof this.sayName != "function"){
    
    
        Person.prototype.sayName = function(){
    
    
            alert(this.name)
        }
    }
}
var person1 = new Person('dsa',14)

**优点:**将组合模式更好的封装起来。

上面用if判断,是防止每次new Person()时都调用一次Person.prototype.sayName=function(){}。

加个if判断,就只有在第一次new Person()时,构建一次sayName函数。第二次再new Person()时,由于原型链上已经有sayName函数了,typeof this.sayName等于’function’,就不用再构建sayName函数了。

6.2.7 寄生构造函数模式

寄生在构造函数的一种方法。

function SpecialArray(){
    
    
    var values = new Array();
    values.push(...arguments);
    values.toPipedString = function(){
    
    
        return this.join('|')
    }
}
var colors = new SpecialArray('red','blue','green')

这样方法可以在特殊情况下使用。比如我们想创建一个具有额外方法的特殊数组但是又不想直接修改Array构造函数,我们可以这样写。

但是这种 new 出来的对象与构造函数或者与构造函数的原型属性之间没有关系。

6.2.8 稳妥构造函数模式

function person(name){
    
    
    var o = new Object();
    o.sayName = function(){
    
    
        console.log(name);
    };
    return o;
}
var person1 = person('kevin');
person1.sayName(); // kevin
person1.name = "daisy";
person1.sayName(); // kevin
console.log(person1.name); // daisy

所谓稳妥对象,指的是没有公共属性,而且其方法也不引用 this 的对象。

猜你喜欢

转载自blog.csdn.net/Pinoochio/article/details/113706671
今日推荐