美文网首页
js中对象object的创建模式

js中对象object的创建模式

作者: jadefan | 来源:发表于2019-10-12 22:23 被阅读0次

对象的创建除了通过字面量,常用模式还包括:

  • 工厂模式
  • 构造函数模式
  • 原型模式
  • 构造函数与原型组合模式
  • 动态原型模式
  • 寄生构造函数模式
  • 稳妥构造函数模式
    我们逐一来看下:

工厂模式

    function createPerson(name, age, job) {
      var obj = new Object();
      obj.name = name;
      obj.age = age;
      obj.job = job;
      return obj;
    } 
    var p1 = createPerson('wang', 28, 'programmer');
    console.log(p1.name);  //wang

优点:可以通过函数可以创建多个类似对象
缺点:无法识别对象,什么意思呢?看一下代码:

    var str = new String();
    console.log(str instanceof Object);  //true
    console.log(str instanceof String);  //true
    console.log(p1 instanceof Object);   //true
    console.log(p1 instanceof createPerson);  //false

通过new String()创建的str,不仅可以识别出是Object,还可以识别出是String
而p1却不行

构造函数模式

    function Person(name) {
      this.name = name;
      this.sayName = function () {
        console.log(this.name);
      }
    }
    var p2 = new Person('wang');
    console.log(p2.name);  //wang 
    console.log(p2 instanceof Object);   //true
    console.log(p2 instanceof Person);  //true

优点:创建的对象可以很好的识别
缺点:定义的方法在多次实例化时会重复创建,耗费资源
验证一下:

    var p3 = new Person('wang');
    console.log(p2.name == p3.name);       //true
    console.log(p2.sayName == p3.sayName); //false

创建同样属性的对象,尽管属性值相同,但方法并不相同
我们知道函数名只是指向函数的指针,所以可以通过指针指向同一个函数

    function Person(name){
      this.name = name;
      this.sayName = sayName;
    }
    function sayName(){
      console.log(this.name);
    }

    var p2 = new Person('wang');
    var p3 = new Person('wang');
    console.log(p2.sayName == p3.sayName); //true

这样将方法提到全局,构造函数内的方法名只赋值函数名指针即可
但这样如果需要的方法较多,会造成全局函数滥用

原型模式

每个函数都有prototype(原型)属性,这个属性是一个指针,指向一个对象,叫原型对象
原型对象包含着由特定类型的所有实例共享的属性和方法

根据定义可以将共用的属性和方法放在原型对象中,实现共享

    function Person() { }
    Person.prototype.name = 'wang'
    Person.prototype.sayName = function () {
      console.log(this.name);
    }

    var p1 = new Person();
    p1.sayName();  //wang
    var p2 = new Person();
    p2.name = 'zhang';
    p2.sayName();  //zhang
    console.log(p1.sayName == p2.sayName); //true

这样即可以灵活定义,方法又指向同一个函数
优点:很好的解决了方法函数的共享问题
缺点:对象的属性都指定了默认值(小问题),对于引用类型的属性共享后,在某个对象中修改会,会影响到其他对象的同名属性(大问题)
验证一下:

    function Person() { }
    Person.prototype.name = 'wang'
    Person.prototype.friends = ['zhang', 'liu'];

    var p1 = new Person();
    console.log(p1.friends);  // ["zhang", "liu"]
    var p2 = new Person();
    p2.friends.push('li');
    console.log(p1.friends);  // ["zhang", "liu", "li"]

p1.friends的两次输出不一致,受到p2修改属性的影响了

构造函数与原型组合模式

    function Person(name,friends) {
      this.name = name;
      this.friends = friends;
     } 
    var p1 = new Person('wang', ['zhang', 'liu']);
    console.log(p1.friends);  //["zhang", "liu"]
    var p2 = new Person('wang', ['zhang', 'liu']);
    p2.friends.push('li');
    console.log(p1.friends);  //["zhang", "liu"]

通过构造函数与原型的组合,就可以避免上面的问题
这种组合模式,是目前使用最广泛、认同度最高的一种创建自定义类型的方法,也可以说是用来定义引用类型的一种默认模式。

动态原型模式

对于将构造函数与原型分开独立的写法,不够直观

    function Person(name, friends) {
      this.name = name;
      this.friends = friends; 
      if (typeof this.sayName != 'function') {
        Person.prototype.sayName = function () {
          console.log(this.name);
        }
      }
    }

在每次调用执行构造函数时,会判断原型中sayName 是否存在,如果存在则证明函数的原型对象已经定义过,所以方法定义部分只会执行一次。

寄生构造函数模式

    function Person(name) {
      var obj = new Object();
      obj.name = name;
      obj.sayName = function () {
        console.log(this.name);
      }
      return obj;
    }
    var p1 = new Person('wang');
    p1.sayName();  //wang

寄生构造与普通工厂很类似,不同之处在于实例化对象时用到了new
寄生构造与构造函数很类似,不同之处在于返回的对象并不是函数的this,而是与函数没有关系的另一个对象

基本思想:创建一个函数,作用仅仅是封装创建对象的代码,然后返回新创建的对象
用途:在特殊情况下用来为对象创建构造函数

假设想创建一个具有额外方法的特殊数组,但不能直接修改Array构造函数

    function SpecialArray(){
      var values = new Array();
      values.push.apply(values,arguments);
      values.toPipedString=function(){
        return this.join('-');
      }
      return values;
    }
    var nums = new SpecialArray(1,2,3,4,5);
    console.log(nums.toPipedString());  //1-2-3-4-5

这种模式下返回的对象与构造函数没有关系,也就不能用instanceof确定类型
所以可用其他模式情况下,优先使用其他模式

稳妥构造函数模式

稳妥对象,指没有公共属性,而且其方法也不引用this的对象
适用于某些安全环境(禁用this和new),或者防止数据被其他程序改动时使用

    function Person(name) {
      var _age;
      var obj = new Object();
      obj.age = function(age){
        _age = age
      };
      obj.sayAge = function () {
        console.log(_age);
      }
      obj.sayName = function () {
        console.log(name);
      }
      return obj;
    }
    var p1 = Person('wang');
    p1.sayName();  //wang
    p1.age(18);
    p1.sayAge();   //18

也就是说该模式下不用this和new,所以内部属性都用私有变量,更新属性需通过访问方法来操作

相关文章

网友评论

      本文标题:js中对象object的创建模式

      本文链接:https://www.haomeiwen.com/subject/jcwcmctx.html