这个系列是我读冴羽老师博客的感悟,
加入了个人的解读和练习题的解答
new Fn() 一共做了 4 件事:
- 生成一个临时空对象
var temp = {}
- 临时对象的原型为构造函数 Fn 的原型
temp.__proto__ = Fn.prototype
- 执行 Fn 函数,把 temp 作为 this,
F.call(temp)
- 在 Fn 里
return this
看一个例子
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.runSpeed = 10 // 10km/h
Person.prototype.run = function () {
console.log('running')
}
var theOne = new Person('Neo', 20)
console.log(theOne.name) //Neo
console.log(theOne.age) //20
console.log(theOne.runSpeed) //10
theOne.run() //running
|
js 中的关键词 new 可以创建一个新对象,这个新对象的原型是 new 后面跟的构造函数的原型,
在上面这个例子中,实例 theOne 的原型是 Person,实例 theOne 可以:
1.访问到构造函数 Person 的属性
2.访问到构造函数 Person 的原型的属性
尝试模拟:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
function objectFactory() {
// 创造一个空对象
var obj = Object({})
//函数的第一个参数是obj的构造函数,使得obj可以访问构造函数的原型的属性
Constructor = [].shift.call(arguments)
//空对象的原型是构造函数的原型
obj.__proto__ = Constructor.prototype
//重新指向this为obj后,执行构造函数,使得obj可以访问构造函数的内部属性
Constructor.apply(obj, arguments)
return obj
}
|
还有一种情况需要考虑,就是构造函数有返回值时,
obj 访问构造函数内部的属性就有了限制,为了实现封装
比如:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
function Person(name, age) {
this.name = name
this.age = age
return {
name: name,
sex: 'male',
}
}
var theOne = new Person('Neo', 20)
//实例theOne只能返回构造函数返回的对象中的属性
console.log(theOne.name) //Neo
console.log(theOne.age) //undefined
console.log(theOne.sex) //male
|
而如果构造函数返回的不是对象
1
2
3
4
5
6
7
8
9
10
11
12
|
function Person(name, age) {
this.name = name
this.age = age
return 'warning: no access'
}
var theOne = new Person('Neo', 20)
//相当于没有返回值进行处理
console.log(theOne.name) //undefined
console.log(theOne.age) //undefined
|
好的,我们来完善一下 objectFactory 方法:
1
2
3
4
5
6
7
|
function objectFactory() {
var obj = Object({})
Constructor = [].shift.call(arguments)
obj.__proto__ = Constructor.prototype
var result = Constructor.apply(obj, arguments)
return typeof result === 'object' ? result : obj
}
|