Please enable Javascript to view the contents

从头学习js-12-模拟实现new

 ·  ☕ 2 分钟

这个系列是我读冴羽老师博客的感悟,
加入了个人的解读和练习题的解答

new Fn() 一共做了 4 件事:

  1. 生成一个临时空对象 var temp = {}
  2. 临时对象的原型为构造函数 Fn 的原型 temp.__proto__ = Fn.prototype
  3. 执行 Fn 函数,把 temp 作为 this,F.call(temp)
  4. 在 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
}
分享

Llane00
作者
Llane00
Web Developer