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

工厂模式
    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 操作符调用构造函数

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,843评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,538评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,187评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,264评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,289评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,231评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,116评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,945评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,367评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,581评论 2 333
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,754评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,458评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,068评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,692评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,842评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,797评论 2 369
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,654评论 2 354

推荐阅读更多精彩内容