摘要:创建对象的多种方式以及优缺点
字面量模式
在计算机科学中,字面量(literal)是用于表达源代码中一个固定值的表示法(notation)。字面量表示的优点就是对象的属性和值对应的方式一目了然
1 | var person = { |
操作对象属性时,可以用.
也可以用[]
。但有些区别:中括号运算符总是能代替点运算符,但点运算符却不一定能全部代替中括号运算符;中括号运算符可以用纯数字、字符串变量的内容、js的关键字和保留字作为属性名,点运算符不能。使用中括号运算符时字符串记得用引号包裹
1 | person.name; // xiaowang |
工厂模式
说白了就是封装,将一段重用性高的代码封装起来,以便多次调用。对象没法识别,因为所有实例都指向一个原型
1 | function Person(name) { |
构造函数模式
构造函数的原理与工厂模式一样:先创建一个对象,再给对象添加上属性和方法。每次创建实例时,每个方法都要被创建一次
构造函数与普通函数的区别:
1.构造函数的首字母大写(约定俗成,小写也没问题);
2.构造函数使用new操作符
使用new关键字创建对象的过程:
1.创建一个新对象
2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
3.执行构造函数中的代码(为这个新对象添加属性)
4.返回新对象
1 | function Person(name) { |
优化一下,将函数定义转移到构造函数外部:
1 | function Person(name){ |
这样所有的实例对象就共享了全局作用域中定义的同一个say函数,但是当对象需要很多方法时,我们要定义很多个全局函数,这样毫无封装性
原型模式
使用构造函数创建实例,每次创建实例都要重新创建一次相同的方法,这是完全没有必要的,而原型模式可以将公共的属性和方法提出来。但要注意的是:构造函数中的this指向的是实例对象,而原型中的this指向原型对象;原型模式下如果引用被一个实例修改,那么所有实例的相同引用都将被修改
1 | function Person() { } |
混合模式(原型模式 + 构造函数模式)
混合模式中构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。每个实例都会有自己的一份实例属性,但同时传递参数又共享着方法,最大限度的节省了内存。
1 | function Person(name) { |
动态原型模式
通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型:
1 | function Person(name) { |
注意:使用动态原型模式时,不能用对象字面量重写原型
1 | function Person(name) { |
使用new新建一个实例person1,假如此时Person.prototype指向A,那么person1的实例原型person1.proto也是指向A。检测到A没有say方法,Person.prototype被修改由指向A改为指向B。但是person1.proto的指向并没有发生改变,还是指向A,所以person1调用say方法时会报错
寄生构造函数模式
从代码上看寄生构造函数模式就是比工厂模式多使用了一个new,构造函数在不返回值的情况下会默认返回新的对象实例,但使用return可以重写返回的值,重写后构造函数返回的对象与构造函数或者构造函数的原型属性之间没有任何关系。这种在可以使用其他模式的情况下,不要使用这种模式
1 | function Person(name) { |
稳妥构造函数模式
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象,稳妥对象最适合在一些安全的环境中。稳妥构造函数模式也无法识别对象所属类型
稳妥构造函数模式与寄生构造函数模式有两点不同:
1.创建实例方法不引用this
2.不使用new操作符调用构造函数
1 | function Person(name) { |