-
Notifications
You must be signed in to change notification settings - Fork 0
Description
new操作符
使用new操作符后跟Object构造函数
let person = new Object()
person.name = 'zyl'
person.age = 26
对象字面量
对象字面量是对象定义的一种简写形式,目的在于简化创建包含大量属性的对象的过程。
let person = {
name: 'zyl',
age: 26,
5: true // 数值属性名会自动转换为字符串
}
虽然let person1 = {}与new Object()相同,但通过对象字面量定义对象时,实际上不会调用Object构造函数(早期版本会调用,Firefox3后不会了)。这是因为字面量法创建对象,强调该对象仅是一个可变的hash映射,而不是从对象中提取的属性嚯方法。现代JS引擎会将{}解析为对象,并把该对象的_proto_指向了Object.prototype。
对象字面量语法代码简洁,是向函数传递大量可选参数的首选方式。
访问对象可以通过点表示法,和方括号表示法,当属性名中包含会导致语法错误的字符,或使用了关键字、保留字,也可以使用方括号表示法。
person['first name'] = 'z' // first name中包含了空格,会导致语法错误
缺点: 使用Object构造函数或对象字面量可以很方便地创建单个对象,但使用同一个接口创建多个具有相同属性和方法的对象时,会产生大量重复代码。为解决这个问题,人们开始使用工厂模式。
工厂模式
function createPerson(name, age, job) {
let o = new Object()
o.name = name
o.age = age
o.sayName = () => {
console.log(this.name)
}
return o
}
let person1 = createPerson('zyl', 26, 'teacher')
let person2 = createPerson('zn', 28, 'singer')
缺点: 将Object构造函数实例的过程封装,虽然解决了创建多个相似对象的问题,但没有解决对象识别的问题,工程模式下所有实例均指向一个原型。
构造函数模式
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function () {
console.log(this.name)
}
}
let person1 = new Pserson('zyl', 26)
let person2 = new Pserson('zn', 28)
构造函数没有显式地创建对象,直接将属性和方法赋给了this对象,没有return语句。创建Person的实例,必须使用new操作符,以这种方式调用实际上会经历以下四个步骤:
- 创建一个新对象
- 将构造函数的作用域赋给新对象(因此this指向了新对象)
- 执行构造函数中的代码(为新对象添加属性)
- 返回新对象
person1和person2分别是Person的实例,这两个对象都有一个constructor属性,该属性指向Person。使用instanceof操作符更可靠的检测对象类型。
console.log(person1 instanceof Person) // true
缺点: 每个方法都要在每个实例上重新创建一遍。函数也是对象,每定义一次函数也就实例化了一个对象。
this.sayName = new Function('console.log(this.name)') // 与声明函数在逻辑上是等价的
console.log(person1.sayName == person2.sayName) // false
优化:
function Person(name, age) {
this.name = name
this.age = age
this.sayName = sayName
}
function sayName() {
console.log(this.name)
}
let person1 = new Person('zyl', 26)
let person2 = new Person('zn', 28)
如此,定义多个全局函数,那自定义的引用类型就丝毫没有封装性可言了。好在这个问题可以通过使用原型模式来解决。