创立目标
创立单个目标:Object 结构函数 和 目标字面量
缺点:运用一个接口创立很多目标,发生很多重复代码
相关代码→
工厂形式
抽象创立特定目标的过程,按照特定接口创立目标
function createPerson(name, age, job) {
var o = new Object()
o.name = name
o.age = age
o.job = job
o.sayName = function () {
console.log(this.name)
}
return o
}
var person1 = createPerson('Nicholas', 29, 'Engineer')
var person2 = createPerson('Greg', 27, 'Doctor')
console.log(person1)
console.log(person2)
工厂形式解决了创立多个相似目标的问题,但没有解决目标辨认问题(怎样知道一个目标的类型)
结构函数形式
除了 Object 和 Array 等原生结构函数,还能够创立自界说的结构函数
结构函数形式 vs 工厂形式
不显式的创立目标
直接将特点和办法赋给 this 目标
没有 return
function Person(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = function () {
console.log(this.name)
}
}
var person1 = new Person('Nicholas', 29, 'Software Engineer')
var person2 = new Person('Greg', 27, 'Doctor')
结构函数用大写字母开头,创立实例时用 new 操作符
结构函数 new 一个目标后:
创立了一个新目标(实例)
新目标内部的[[Prototype]]特性被赋值为结构函数的prototype特点(一起指向原型)
将结构函数的效果域(即 this)赋给新目标
执行结构函数中的代码(即:为这个目标增加新特点)
返回新目标或非空目标
创立的目标(实例)既是 Object 的实例,又是结构函数的实例,其 constructor 特点指向结构函数
能够保证自界说结构函数的实例被标识为特定的类型,是结构函数形式胜过工厂形式的地方
console.log(person1.constructor === Person) // true,constructor 特点指向结构函数
console.log(person2.constructor === Person) // true,constructor 特点指向结构函数
console.log(person1 instanceof Object) // true,person1是Object的实例
console.log(person1 instanceof Person) // true,person1是Person的实例
console.log(person2 instanceof Object) // true,person2是Object的实例
console.log(person2 instanceof Person) // true,person2是Person的实例
结构函数也能够运用函数表达式表示,实例化不传参数时,结构函数后面的括号可加可不加
var PersonExpression = function () {
// 结构函数的函数表达式
this.name = 'Jake'
this.sayName = function () {
console.log(this.name)
}
}
var personNoBrackets = new PersonExpression() // 实例化不传参数,可不加括号
结构函数也是函数
结构函数与一般函数仅有的区别是调用方式不同:运用new操作符调用的就是结构函数,不运用的是一般函数
默认情况下,调用函数时的 this 指向 Global 目标(浏览器中指向 window 目标)
var person3 = new Person('Nicholas', 29, 'Software Engineer') // 用结构函数创立目标
person3.sayName() // 'Nicholas'
Person('Greg', 27, 'Doctor') // 'Greg',不运用new操作符,直接调用
global.sayName() // 直接调用函数,this指向Global目标(浏览器中指向window目标)
var o = new Object() // 新目标o
var p = new Object() // 新目标p
Person.call(o, 'Kristen', 25, 'Nurse') // 将目标o指定为Person()内部的this值,call()分别传入每个参数
Person.apply(p, ['Kristen', 25, 'Nurse']) // 将目标o指定为Person()内部的this值,apply()传入参数数组
o.sayName() // 'Kristen'
p.sayName() // 'Kristen'
结构函数的问题
界说的办法会在每个实例上都创立一遍,每界说一个函数,就实例化一个目标,创立 2 个完结相同任务的 Function 实例没有必要
function Person2(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = new Function(console.log(this.name)) // 与声明函数逻辑等价,每创立一个目标就要创立一个Function实例
}
console.log(person1.sayName === person2.sayName) // false,新目标的2个办法的效果域链和标识符解析不同
将目标的办法移到结构函数外部,防止屡次创立 Function 实例
function Person3(name, age, job) {
this.name = name
this.age = age
this.job = job
this.sayName = sayName
}
function sayName() {
console.log(this.name) // 将sayName设置成大局函数
}
var person4 = new Person('Nicholas', 29, 'Software Engineer')
结构函数仍未解决的问题:① 创立的大局函数实际上只需要被某个目标中调用;② 若目标有多个办法,需创立很多大局办法
原型形式
每个函数都有 prototype 特点,该特点是一个指针,指向函数(经过调用结构函数而创立的那个目标实例的)原型目标
运用原型目标的好处是,其所有目标实例同享其所包含的特点和办法
function PersonPrototype() {}
PersonPrototype.prototype.name = 'Nicholas' // 为PersonPrototype的原型目标增加特点
PersonPrototype.prototype.age = 29 // 为PersonPrototype的原型目标增加特点
PersonPrototype.prototype.job = 'Software Engineer' // 为PersonPrototype的原型目标增加特点
PersonPrototype.prototype.sayName = function () {
// 为PersonPrototype的原型目标增加办法
console.log(this.name)
}
var person5 = new PersonPrototype()
var person6 = new PersonPrototype()
person5.sayName() // 'Nicholas'
person6.sayName() // 'Nicholas'
console.log(person5.sayName === person6.sayName) // true,原型目标上创立的特点和办法