Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

17、对象的创建 #17

Open
shengq666 opened this issue Jun 28, 2020 · 5 comments
Open

17、对象的创建 #17

shengq666 opened this issue Jun 28, 2020 · 5 comments

Comments

@shengq666
Copy link
Owner

No description provided.

@shengq666
Copy link
Owner Author

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

  • 工厂模式
  • 对象字面量
  • OBject.create()

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

@shengq666
Copy link
Owner Author

shengq666 commented Jun 29, 2020

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)

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

  • 没有显示的创建对象
  • 直接将属性和方法复制给了 this 对象
  • 没有 return 语句

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

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

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. 原型模式的最大问题是由其共享的本性所导致的。原型中所有属性是被很多实例共享的,这种共享对于函数非常合适。对于那些包含基本值的属性倒 也说得过去,毕竟(如前面的例子所示),通过在实例上添加一个同名属性,可以隐藏原型中的对应属 性。然而,对于包含引用类型值的属性来说,问题就比较突出了。(因为引用类型是按照地址存储的)

@shengq666 shengq666 reopened this Jun 29, 2020
@shengq666
Copy link
Owner Author

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) 
          }
    }
}
    使用动态原型模式时,不能使用对象字面量重写原型。前面已经解释过了,如果 在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系。

@shengq666
Copy link
Owner Author

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"

@shengq666
Copy link
Owner Author

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 操作符对这种对象也没有意义。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant