今天在做面试题的时候碰到一道题,感觉涉及的知识点还挺多的,想着谈一谈自己学到的东西,也算是学以致用吧。
目前本人还在学习中,如果讲错了或者需要补充的欢迎请大家指正,谢谢!
面试题出自:牛客最新前端JS笔试百题 - 掘金中的程序题,如有侵权,请及时联系,第一次写blog,请见谅。
话不多说,上题:
下列程序的输出结果是多少?你能理清楚test函数的this指向吗?
var a = 5;
function test() {
a = 0;
alert(a);
alert(this.a);
var a;
alert(a);
}
new test();
解题过程:
初看这道题的时候,有一点困惑,为什么构造函数的函数名首字母没有大写?在网上搜了一下,原来还真有别人问过JS里构造函数首字母不大写有什么影响-前端-CSDN问答,觉得挺有道理的,如果有更好的答案,请分享一下,互相进步,上述链接得出的结论如下:
JS里构造函数首字母不大写有什么影响没任何影响,只不过一般大写,这是一个规范,普通函数首字母是小写,为了区别构造函数首字母大写。
接着看题,
先看new test(),因为new关键字会创建一个对象实例,而里面的this指向这个实例对象。
var a = 5;
function test() {console.log(this); // test{} this指向了一个空对象实例
a = 0; //非严格模式下,a可以先赋值,再声明,a存在变量提升的情况
alert(a); // 0
alert(this.a); // undefinded
var a;
alert(a); // 0
}
new test();console.log(a); // 5 从这里也可以证明a不是全局变量,因为如果函数中的a=0位全局变量的话,那么这个打印输出的结果就应该为0才对
学过构造函数的都知道,要想给构造函数添加属性或方法,需要用到this.xxx=ccc或者this.xxx=function(){}格式来赋值操作,如果未赋值就使用了,就会得出undefined结论,所以可以看出上述题目中的this.a为undefined。
至于上述题目中的两个a结果为什么为0?个人理解如下。
在test函数中,a=0在var a之前,赋值在声明之前,非严格模式下是允许的;在第一个alert(a)中,根据就近原则,往上查找,找到了a=0,所以第一个alert(a)结果为0;然后程序来到了alert(this.a)得出undefined(this.a未定义,所以报undefined);程序执行到第二个alert(a),也是往上寻找a的值(a存在变量提升的情况),找到了a=0,所以第二个alert(a)结果也为0。
下面还有两个小例子,
\\1.
var a = 5;
function test() {console.log(this); // test{} this指向了一个空对象实例
a = 0; //只要在一个函数中有声明a,则这个a=0就不是全局变量,存在变量提升
alert(a); // 0
alert(this.a); // undefinded
var a=12;
alert(a); // 12 这个a会根据就近原则往上查找,离它最近的是12,所以为12
}
new test();console.log(a); //5
//2.函数中未声明变量但是赋了值的,则注意为全局变量
var a = 5;
function test() {console.log(this); // test{} this指向了一个空对象实例
a = 0; //因为在函数中未声明a,所以a=0为全局变量
alert(a); // 0
alert(this.a); // undefinded
}
new test();console.log(a); /// 0 因为在test函数中未声明a,所以test函数中的a=0为全局变量
综上所述题目的答案为:
下列程序的输出结果是多少?------0 undefined 0
你能理清楚test函数的this指向吗?-------test函数中的this指向实例对象test{}
知识总结:
1)new关键字会创建一个对象实例,而里面的this指向这个实例对象;如果要声明属性和方法,需要用到this.xx=cc或者this.xx=function(){}来声明;
2)构造函数首字母不大写有什么影响没任何影响,只不过一般大写,这是一个规范,普通函数首字母是小写,是为了区别构造函数首字母大写(最好按规范走);
3)函数中,如果未声明变量但是赋了值的,则注意为全局变量;
如果先赋值了,下面再声明,则注意为非严格模式,存在变量提升(注意声明的关键字不能为let和const等)。