KFCVme50-CrazyThursday / sheng-study

个人学习总结与代码知识点
1 stars 0 forks source link

17、对象的创建 #17

Open KFCVme50-CrazyThursday opened 4 years ago

KFCVme50-CrazyThursday commented 4 years ago

这个记不太清楚了,脑子中出现的暂时有三种:

晚上回去瞅两眼红皮书,关机下班

KFCVme50-CrazyThursday commented 4 years ago

1. 工厂模式

functiong createPerson(name, age) {
    var o = new Object();
    o.name = this.name;
    o.age = this.age;
    o.sayName = function() {
         console.log(this.name)
   }
}

var person1 = createPerson('sq', 24)
var person2 = createPerson('ax', 24)

缺点:对象无法识别,因为所有的实例都指向一个原型

2. 构造函数模式

function  Person(name, age) {  // **函数名开头大写**
    this.name = name;
    this.age = age;
    this.sayName = function() {
         console.log(this.name)
   }
}

var person = new Person('sq', 24)
var person1 = new Person('ax', 24)

构造函数模式 与 工厂模式的不同:

缺点:解决了 工厂模式 存在的问题,但每次创建实例时,方法都要被重新创建一次。

因为构造函数模式每次创建实例时方法都要被重新创建一次,因此可以针对该点进行优化,将方法转移到外部。

function  Person(name, age) {  // **函数名开头大写**
    this.name = name;
    this.age = age;
    this.sayName = sayName
}

function sayName () {
    console.log(this.name)
}

var person = new Person('sq', 24)
var person1 = new Person('ax', 24)

缺点:这是个 🔨 的优化

3. 原型模式

function Person() {}
Person.prototype.name = "sq"; 
Person.prototype.sayName = function() {
    console.log(this.name)
}
var person1 = new Person(); 
person1.sayName(); //"sq"

var person2 = new Person();
person2.sayName(); //"sq"

person1.sayName == person2.sayName ; //true

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

更简单的原型语法: 对象字面量形式,看起来更加优雅点

funtion Person() {}
Person.prototype = {
    name: 'sq',
    age: 24,
    sayName: function() {
          console.log(this.name)
    }
}

var friend = new Person();

alert(friend instanceof Object);   //true
alert(friend instanceof Person);   //true
alert(friend.constructor == Person);   //false
alert(friend.constructor == Object);  //true

缺点:重写了原型,丢失了constructor属性。

解决constructor属性丢失问题:

funtion Person() {}
Person.prototype = {
    constructor : Person,
    name: 'sq',
    age: 24,
    sayName: function() {
          console.log(this.name)
    }
}

缺点:原型模式该有的缺点还是有

  1. 它省略了为构造函数传递初始化参数这一环节,结果所有实例在 默认情况下都将取得相同的属性值
  2. 原型模式的最大问题是由其共享的本性所导致的。原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒 也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属 性。然而,对于包含引用类型值的属性来说,问题就比较突出了。(因为引用类型是按照地址存储的)
KFCVme50-CrazyThursday commented 4 years ago

4. 组合使用构造函数模式和原型模式

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。 结果,每个实例都会有自己的一份实例属性的副本, 但同时又共享着对方法的引用,最大限度地节省了内存。 另外,这种混成模式还支持向构造函数传递参 数;可谓是集两种模式之长,也是目前使用最广泛的一种方式

funtion Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype = {
    constructor : Person,
    sayName: function() {
          console.log(this.name)
    }
}
缺点:冴羽 大大博客里看到的一句话:有的人就是希望全部都写在一起,即更好的封装性 hhhhhhhh

5. 动态原型模式

funtion Person(name, age) {
    this.name = name;
    this.age = age;
    if( typeof this.sayName != 'funtion' ) {
          Person.prototype.sayName = function() {
              console.log(this.name) 
          }
    }
}
    使用动态原型模式时,不能使用对象字面量重写原型。前面已经解释过了,如果 在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。
KFCVme50-CrazyThursday commented 4 years ago

6. 寄生构造函数模式

funtion Person(name, age) {
    var o = new Object() 
    o.name = name;
    o.age = age;
    o.sayName = function() {
        console.log(this.name)
    }
    return o;
}
var people = new Person('sq', 24)

Person 创建了一个新对象,初始化对象后又返回该对象。除了使用 new 操作符并把使用的包装函数叫做构造函数之外,这个模式跟工厂模式其实 是一模一样的。构造函数在不返回值的情况下,默认返回新对象实例。而通过在构造函数末尾添加一个 return 语句,可重写调用构造函数时返回的值。

注意:首先,返回的对象与构造函数或者与构造函数的原型属 性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。为此, 不能依赖 instanceof 操作符来确定对象类型。由于存在上述问题,我们建议在可以使用其他模式的情 况下,不要使用这种模式。

这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊 数组。由于不能直接修改 Array 构造函数,因此可以使用这个模式。

function SpercialArr () {
    var values = new Array();
    values.push.apply(values, arguments);
    values.toPipedString = function() {
        return this.join("|")
    }
    return values;
}

var colors = new SpecialArray("red", "blue", "green"); 
alert(colors.toPipedString()); //"red|blue|green"
KFCVme50-CrazyThursday commented 4 years ago

7. 稳妥构造函数模式

所谓稳妥对象,指的是没有公共属性,而且其方法也不引用 this 的对象。稳妥对象最适合在 一些安全的环境中(这些环境中会禁止使用 this 和 new),或者在防止数据被其他应用程序(如 Mashup 程序)改动时使用。

稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:

  1. 新创建对象的 实例方法不引用 this
  2. 不使用 new 操作符调用构造函数。
function Person(name, age) {
    //创建要返回的对象
    var o = new Object() 
    //可以在这里定义私有变量和函数
    //添加方法
    o.sayName = function() {
        console.log(this.name)
    }
    return o;
}

var friend = Person("Nicholas", 29, "Software Engineer");
 friend.sayName(); //"Nicholas"

这样,变量 friend 中保存的是一个稳妥对象,而除了调用 sayName()方法外,没有别的方式可 以访问其数据成员。即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传 入到构造函数中的原始数据。稳妥构造函数模式提供的这种安全性,使得它非常适合在某些安全执行环 境

    与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也 没有什么关系,因此 instanceof 操作符对这种对象也没有意义。