You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
function Foo() {
getName = function () {
alert(1)
}
return this
}
Foo.getName = function () {
alert(2)
}
Foo.prototype.getName = function () {
alert(3)
}
var getName = function () {
alert(4)
}
function getName() {
alert(5)
}
//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
function User(name) {
var name = name //私有属性
this.name = name //公有属性
function getName() { //私有方法
return name
}
}
User.prototype.getName = function () { //公有方法
return this.name
}
User.name = 'Wscats' //静态属性
User.getName = function () { //静态方法
return this.name
}
var Wscat = new User('Wscats') //实例化
第一问
Foo.getName();
这个不用多说,返回2.
执行的是Foo函数的静态属性getName方法
这里复习下一些定义
个人理解:
公有方法必须实例化才能访问,是因为查找对象的属性时,如果该对象没有这个属性,会在原型链上查找,也就是会在对象的__proto__上继续查找,但是不会查找自身的prototype,而__proto__指向的是这个对象的构造函数的prototype。
也就是说,通过构造函数实例化一个对象后,这个对象就可以通过__proto__访问到构造函数的prototype上的方法。
第二问
直接调用getName函数。
这个明显是只和4和5有关了
4是函数表达式,5是函数声明
这里有个陷阱
函数表达式的值是在JS运行时确定,并且在表达式赋值完成后,该函数才能调用
函数声明在JS解析时进行函数提升,因此在同一个作用域内,不管函数声明在哪里定义,该函数都可以进行调用
这题的考核就是在这个地方,变量提升
第三问
Foo().getName()
先执行Foo(),再调用Foo()的返回值调用getName()调用Foo(),先从函数作用域内寻找getName这个变量,没有找到,再向当前函数作用域上层,找到了,第四个函数定义的getName会被覆盖。
接下来返回this,这里直接调用Foo(),this直接指向window。
那么执行
Foo().getName()
就相当于window.getName()
,直接执行第四个函数,但是第四个函数刚刚已经被覆盖了,所以返回的是1。这道题考察的一个是变量作用域,一个是this指向。
第四问
直接调用getName(),也就是window.getName(), 第一问的Foo函数已经把第五个函数给覆盖了,所以返回的结果是1。
第五问
new Foo.getName()
这题考察的是JS的运算符优先级问题,这是我做这道题之前都没有去了解过的知识点。
下面是JS运算符的优先级表格,从高到低排列。可参考MDN运算符优先级
new (带参数列表)比new (无参数列表)高比函数调用高,跟成员访问同级
点的优先级(18)比new无参数列表(17)优先级高
当点运算完后又因为有个括号(),此时就是变成new有参数列表(18),所以直接执行new,当然也可能有朋友会有疑问为什么遇到()不函数调用再new呢,那是因为函数调用(17)比new有参数列表(18)优先级低
最后结果就是2
第六问
new有参数列表(18)跟点的优先级(18)是同级,同级的话按照从左向右的执行顺序
构造函数的返回值
在传统语言中,构造函数不应该有返回值,实际执行的返回值就是此构造函数的实例化对象。
而在JS中构造函数可以有返回值也可以没有。
没有返回值则按照其他语言一样返回实例化对象。
若有返回值则检查其返回值是否为引用类型。如果是非引用类型,如基本类型(String,Number,Boolean,Null,Undefined)则与无返回值相同,实际返回其实例化对象。
若返回值是引用类型,则实际返回值为这个引用类型。
原题中,由于返回的是this,而this在构造函数中本来就代表当前实例化对象,最终Foo函数返回实例化对象。
之后调用实例化对象的getName函数,因为在Foo构造函数中没有为实例化对象添加任何属性,当前对象的原型对象(prototype)中寻找getName函数。
答案是3
參考地址
The text was updated successfully, but these errors were encountered: