作者:cometcui | 来源:互联网 | 2023-09-23 10:49
JavaScript中函数与构造函数的关系-我们都知道,当一个函数被声明时它便拥有prototype属性,且此函数可作为构造函数调用,无论其函数体内有没有this,调用完成后,函数
我们都知道,当一个函数被声明时它便拥有prototype
属性,且此函数可作为构造函数调用,无论其函数体内有没有this,调用完成后,函数的prototype属性将会赋值给新建对象的proto属性。
function Person(name){
this.name = name
}
function Animal(){}
Person.hasOwnProperty('prototype') //true
Animal.hasOwnProperty('prototype') //true
let john = new Person('john')// It is Ok
let pig = new Person('pig')// It is Ok,too
但是,上面只是一般的情况,以下有几种特例,函数无法作为构造函数被调用:
class Person{
static getName(){
return 'john'
}
}
class Animal{
getName(){
return 'pig'
}
}
let pig = new Animal()
Person.getName.prototype //undefined
pig.getName.prototype //undefined
let person = new Person.getName() //Type Error, because Person.getName is not a constructor
let p = new pig.getName() //Type Error, because pig.getName is not a constructor
有上可知,类的静态函数和实例函数都没有prototype
属性,也都无法进行实例化。我们可以猜想,是不是因为没有prototype属性,我们才无法进行实例化,所以我们尝试为静态函数添加prototype属性:
class Person{
static getName(){
return 'john'
}
}
let proto = {}
proto.cOnstructor= Person.getName()
Person.getName.prototype = proto
new Person.getName() //still Error
从上面代码我们可以知道, 即使有了prototype属性,静态方法也无法作为构造函数实例化,因此我们尝试用另一种方法声明类的静态方法:
class Person{
static getName = function(){
return 'john'
}
}
Person.getName = hasOwnProperty('prototype') //true
let person = new Person.getName()// It is Ok
从上面代码可知,当类静态函数通过赋值声明时,我们可以将其作为构造函数实例化,那是不是只要通过赋值声明的函数都可以实例化,我们进行进一步的验证:
class Person{
static getName = () => {return 'john'}
}
Person.getName = hasOwnProperty('prototype') //false
let person = new Person.getName()// Error
let Animal = () => {}
Animal = hasOwnProperty('prototype') //false
let animal = new Animal()// Error
我们可以进一步得知,当箭头函数赋值给静态函数时,静态函数无法作为构造函数实例化,且箭头函数单独使用时也无法进行实例化,因此我们可以得知函数实例化的关键是function
关键字
总结
从上面的一步步验证我们可以知道,一个函数能否作为构造函数被实例化的关键在于函数的声明方式,而不是有无prototype
属性或者函数的存在方式。只有使用function
关键字声明的函数才是构造函数,反之,使用箭头函数或者ES6类函数简写声明的方式所声明的函数,都无法作为构造函数使用。