类数组的length
var obj = {
"2" : 3,
"3" : 4,
"length" : 2,
"splice" : Array.prototype.splice,
"push" : Array.prototype.push
}
obj.push(1)
obj.push(2)
console.log(obj)
看到这道面试题,心里是否有答案了?我们看下打印结果
看到这个题,要先知道数组的push方法,数组中的push方法是根据数组的length来对数组末尾进行添加元素,在普通的对象中添加length属性和数组的splice方法,obj就会以数组的形式出现,但是他并不是数组,所以obj.push(1)就相当于obj[length]=1,所以对象的属性‘2’就变成了1,length=3,obj.push(2)就相当于obj[3]=2,由于打印时未给数组下标为为0和1设值,所以为空
this指向和关键字new
function Foo() {
getName = function () { console.log(1); };
return this;
}
Foo.getName = function () { console.log(2);};
Foo.prototype.getName = function () { console.log(3);};
var getName = function () { console.log(4);};
function getName() { console.log(5);}
//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
在控制台打印的结果是2,4,1,1,2,3,3
这道题里面含有this指向问题和new的用法,Foo.getName()这个打印结果大家都知道是2,getName()打印的是4,这里可能会问为什么不是5呢?因为var getName = function () { console.log(4);}是个表达式声明的函数,所以getName指的是这个表达式声明的函数,所以打印的是4;
Foo().getName()这个我们要分两步来看,Foo函数的执行,全局的变量getName变成了function () { console.log(1); };又因为函数Foo返回的是window对象;所以打印的是1;所以后面getName()的执行打印也是1
new Foo.getName()这个考查了new的用法,new做了五件事;创建一个新的对象,将新对象的proto属性指向构造函数的原型对象,将this指向新对象,执行构造函数内部代码,返回新对象;所以new Foo.getName()打印的是2;所以后面的new Foo().getName()是Foo的实例对象的getName方法,所以打印的是3;还有后面的new new Foo().getName()打印的也是3;
对象健名的转换
var a={},b='123',c=123;
a[b]='b';
a[c]='c;
console.log(a[b]);
var a={},b=Symbol('123'),c=Symbol(123);
a[b]='b';
a[c]='c;
console.log(a[b]);
控制台打印的是c和b
对象的键名只能是字符串和symbol类型,其他类型都会转换成字符串类型,对象转字符串会默认调用toString方法;由于c是数字类型,所以会将它转换成字符串类型‘123’;由于b为‘123’,所以会覆盖b,所以a[b]打印的是c;第二个例子因为b和c都是Symbol类型,所以都不用转成字符串类型,又由于Symbol的唯一性,所以也不会存在覆盖问题,所以打印的是b
作用域
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();<br>//1
控制台打印的是1
js中只有词法作用域,也就是说js中的作用域是在它定义时确定的作用域,而不是它被执行时确定的作用域,所以这道题中的value还是指向window中的value的值
在网上经常看到这样的一道面试题:
var foo = 1;
(function foo(){
foo = 100;
console.log(foo);
}())
console.log(foo);
控制台打印的是foo函数和全局的foo,可能js的初学者会认为foo变成100了,在js执行前,js引擎会进行预编译,也就是变量提升和函数提升,在执行到自执行函数foo=100,js中函数名是不能对函数名进行修改的,所以打印的还是foo函数的本身,console.log(foo)打印的还是全局作用域的foo的值1