一 隐式转换
以下代码输出什么?
console.log(3+4+'5');
console.log(+'3'+4+5);
console.log([]==![]);
console.log((!+true+[]+false).length);
console.log((!+[]+[] +![]).length);
console.log(3+4+'5');和console.log(+'3'+4+5); 分别输出 75 和 12 因为+ 只有当作正号使用时才会将string 转变为number。
如果 修改为 console.log(3+4+ +'5');那么输出为12。
console.log([]==![]); 输出为true ,因为第一步有! 先把![]转变为false,现在是[]==false,第二步转变为基本数据类型,[]转变为'',false转变为0,现在是''==0,第三步是将字符串转为数字,''转变为数字为0, 此时便是0==0 为true。
console.log((!+true+[]+false).length);输出为10,因为第一步+true 隐式转变为1,然后执行!1 取反为false,[]转为''空字符串,false不变,现在就变为false+''+false,最后为'falsefalse'.length 输出为10。
console.log((!+[]+[] +![]).length);输出为9,因为第一步+[],转变为0,然后执行!0 取反为true,[]转变为''空字符串,![] 取反为false,现在变为true+''+false,最后就为'truefalse'.length 输出为9.
二 var和let的区别
以下代码输出什么?
a()
var k='word'
function a(){
console.log(k);
}
b()
let z='word'
function b(){
console.log(z);
}
for(var i=0;i<5;i++){
setTimeout(() => {
console.log(i);
}, 1000);
}
for(let i=0;i<5;i++){
setTimeout(() => {
console.log(i);
}, 1000);
}
a()输出为undefined,var 声明的变量和函数声明会被提升,到作用域的顶部,但变量赋值不会被提升。所以此时k的值为undefined。
b()会报错,因为let声明的变量存在暂时性死区,不允许在声明之前使用,所以此时会直接报错,Uncaught ReferenceError: Cannot access 'z' before initialization
for(var i=0;i<5;i++)中的i会输出5个5,因为var声明的变量为全局作用域,此时setTimeout执行时i已经为5了。
for(let i=0;i<5;i++)中的i会输出0 1 2 3 4 ,因为let声明的变量有块级作用域,每一个i都是单独变量,此时setTimeout执行时输出i都是单独变量。
三 深浅拷贝
以下代码输出什么?
var a={
name:'小芳'
}
var b=a
b.name='小甜'
console.log(a);
var c={
name:'小雪'
}
var d={...c}
d.name='小可'
console.log(c);
console.log(a); 输出为{name: "小甜"},因为当你把变量a赋值给变量b时,它们实际上指向相同的对象。所以当你改变变量b的属性时,实际上也改变了对象本身,因此a和b都会输出{name: ‘小甜’}。因为它们指向同一个对象,所以对象的属性被修改后,无论通过a还是b访问,都会得到相同的值。
console.log(c);输出为{name: "小雪"},因为var d={...c} 使用了扩展运算符进行了浅拷贝,使用浅拷贝时,创建了一个新的对象dd和原对象c是两个独立的对象,它们分别拥有各自的内存空间。但特别注意浅拷贝只能拷贝第一层的数据,如果其中拷贝的对象中有引用数据类型,那么此时c和d还是会指向同一个对象,浅拷贝只能实现一层数据拷贝。
四 this指向
以下代码输出什么?
function fun(val){
this.c +=val
}
fun.c=0
console.log(fun(1));
console.log(fun(1));输出为undefined,因为函数内的this 指向为window,而window没有为c的属性,所有输出为undefined。