一、构造函数
先看下构造函数的定义
ECMAScript 中的构造函数是用于创建特定类型对象的。构造函数也是函数,只是使用
new
操作符调用构造函数会执行如下操作:
(1) 在内存中创建一个
新对象
(2) 这个新对象内部的
[[Prototype]]
特性被赋值为构造函数的
prototype
属性
(3) 构造函数内部的
this
被赋值为这个新对象(即 this 指向新对象)
(4) 执行构造函数内部的代码(给新对象添加属性)
(5) 如果构造函数返回
非空对象
,则返回该对象;否则,返回刚创建的新对象
二、分析
如果不清楚构造函数的定义,就没有必要看这部分了
根据定义,这里将构造函数分为两种:有无返回非空对象。具体区别在哪儿,之前从未细想过
示例1:实例在原型上的不同
function Foo(name) {
this.name = name
}
function Bar(name) {
this.age = 27
return { name }
}
let foo = new Foo('Tom'), bar = new Bar('Tom')
console.log(foo.__proto__ === Foo.prototype) // true
console.log(bar.__proto__ === Bar.prototype) // false
上图中也可以看出,foo的原型指向Foo的原型,而bar的原型指向Object的原型
示例2
通过这个例子更明显的对比构造函数中的
this
与
return
的实例
function Foo(name) {
const _this = this
this.name = name
function test(){
console.log(this, _this)
}
return {
name: 'Tom',
test
}
}
let foo = new Foo('Anne')
console.log(foo)
foo.test()
执行
foo.test()
this
打印的是foo,即,实例化时return出来的对象
_this
打印的是实例化过程中创建的新对象,根据定义,该对象原型指向构造函数的原型。相比之下,前者是对象字面量,其原型指向Object的原型
原型上的区别,意味着,上例中,foo的原型也不指向 Foo的原型,原型的构造函数也并非 Foo。
因此,foo无法访问Foo的原型属性与方法:
function Foo(name) {
const _this = this
this.name = name
function test(){
return _this
}
return {
name: 'Tom',
test
}
}
let foo = new Foo('Anne'), _this = foo.test()
Foo.prototype.age = 18
Foo.prototype.func = function() {
console.log(this.name, this.age)
}
console.log(!!foo.func, !!_this.func) // false true
_this.func() // Anne 18
针对这点,可以在构造函数内手动将返回的对象原型指向构造函数的原型
如果用不上原型链的话,可以直接忽视这点
function Foo(name) {
let res = {}
res.__proto__ = Foo.prototype
return Object.assign(res, { name })
}
let foo = new Foo('Anne')
Foo.prototype.age = 20
console.log(foo.age) // 20