js创建对象的几种方式和优缺点

2019-08-21  本文已影响0人  李友胜
工厂模式
    function createPerson(name, age, job) {
        var p = new Object()
        p.name = name;
        p.age = age;
        p.job = job;
        p.sayName = function () {
            alert(this.name)
        }
        return p;
    }

    var person1 = createPerson('Lusen', 26, 'coder')
    var person2 = createPerson('Eugine', 26, 'teacher')

缺点:没有解决对象识别,所有的实例都指向一个原型

构造函数模式
function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function () {
            alert(this.name)
        }
    }

    var person1 = new Person('Lusen', 26, 'coder')
    var person2 = new Person('Eugine', 26, 'teacher')
    
    // 这两个对象都有一个constructor属性,都指向Person
    person1.constructor === Person // true
    person2.constructor === Person // true
    person1 instanceof Person // true

创建构造函数的实例,必须使用new操作符,经历以下四步:
1. 创建一个新对象
2. 将构造函数的作用域赋给新对象(this指向了这个新对象)
3. 执行构造函数中的代码(为这个新对象添加属性)
4. 返回新对象
优点:实例可以识别为一个特定的类型
缺点:每次创建实例,每个方法都要创建一次

构造函数优化:

将sayName函数的定义转移到了构造函数外部,这样构造函数内部sayName包含的是一个指向外部函数的指针。

function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = sayName;
    }

function sayName = function(){
        alert(this.name)
  }

 var person1 = new Person('Lusen', 26, 'coder')
 var person2 = new Person('Eugine', 26, 'teacher')

优点:解决了每个方法都要被重新创建的问题
缺点:对象如果有多个方法,需要定义多个全局函数,自定义的引用类型没有封装性而言。

原型模式

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象。好处是让所有实例对象都共享它原型对象的属性和方法。

    function Person() {

    }

    Person.prototype.name = 'Lusen'
    Person.prototype.age = 26
    Person.prototype.job = 'coder'
    Person.prototype.sayName = function () {
        alert(this.name)
    }

    var person1 = new Person()
    person1.sayName()  // Lusen

    var person2 = new Person()
    person2.sayName() // Lusen

优点:方法不会重新创建
缺点:1. 所有的属性和方法都共享 2. 不能初始化参数

原型模式优化
    function Person() {

    }

    Person.prototype = {
        constructor: Person,
        name: 'Lusen',
        sayName: function(){
            alert(this.name)
        }
    }

    var person1 = new Person()
组合模式

构造函数和原型模式组合:

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

function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
    }

    Person.prototype = {
        constructor: Person,
        sayName: function () {
            alert(this.name)
        }
    }
动态原型模式
    function Person(name, age, job) {
        this.name = name;
        this.age = age;
        this.job = job;
        if (typeof this.sayName != 'function') {
            Person.prototype.sayName = function () {
                alert(this.name)
            }
        }
    }
寄生构造函数模式

这种模式的基本思想是创建一个函数,函数的作用仅仅是封装创建对象的代码,最后返回对象,最后用new 操作符实例化。

function Person(name, age, job) {
       var p = new Object()
       p.name = name;
       p.age = age;
       p.job = job;
       p.sayName = function () {
           alert(this.name)
       }
       return p;
   }

构造函数在不返回值得情况下,默认返回新对象实例。而在构造函数末尾添加一个return语句,可以重写构造函数返回的值。
如果我们要创建一个有额外方法的特殊数组,但是又不能直接修改Array构造函数可以使用这个模式

function SpecialArray() {
       var values = new Array()

       values.push.call(values, arguments)

       values.toPipedString = function () {
           return this.join('|')
       }

       return values;
   }

   var colors = new SpecialArray('red', 'blue', 'green');
稳妥构造函数模式
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 的对象。

与寄生构造函数模式有两点不同:

  1. 新创建的实例方法不引用 this
  2. 不使用 new 操作符调用构造函数

稳妥对象最适合在一些安全的环境中。
稳妥构造函数模式也跟工厂模式一样,无法识别对象所属类型。

上一篇 下一篇

猜你喜欢

热点阅读