let a = 1
function b(a) {
a = 2
console.log(a)
}
b(a)
console.log(a)
复制代码
答案
2、1
解析
首先基本类型数据是按值传递的,所以执行b函数时,b的参数a接收的值为1,参数a相当于函数内部的变量,当本作用域有和上层作用域同名的变量时,无法访问到上层变量,所以函数内无论怎么修改a,都不影响上层,所以函数内部打印的a是2,外面打印的仍是1。
function a (b = c, c = 1) {
console.log(b, c)
}
a()
复制代码
答案
报错
解析
给函数多个参数设置默认值实际上跟按顺序定义变量一样,所以会存在暂时性死区的问题,即前面定义的变量不能引用后面还未定义的变量,而后面的可以访问前面的。
let a = b = 10
;(function(){
let a = b = 20
})()
console.log(a)
console.log(b)
复制代码
答案
10、20
解析
连等操作是从右向左执行的,相当于b = 10、let a = b,很明显b没有声明就直接赋值了,所以会隐式创建为一个全局变量,函数内的也是一样,并没有声明b,直接就对b赋值了,因为作用域链,会一层一层向上查找,找了到全局的b,所以全局的b就被修改为20了,而函数内的a因为重新声明了,所以只是局部变量,不影响全局的a,所以a还是10。
var a = {n:1}
var b = a
a.x = a = {n:2}
console.log(a.x)
console.log(b.x)
复制代码
答案
undefined、{n: 2}
解析
恕笔者不才,这道题笔者做一次错一次。
反正按照网上大部分的解释是因为.运算符优先级最高,所以会先执行a.x,此时a、b共同指向的{n: 1}变成了{n: 1, x: undefined},然后按照连等操作从右到左执行代码,a = {n: 2},显然,a现在指向了一个新对象,然后a.x = a,因为a.x最开始就执行过了,所以这里其实等价于:({n: 1, x: undefined}).x = b.x = a = {n: 2}。
var arr = [0, 1, 2]
arr[10] = 10
console.log(arr.filter(function (x) {
return x === undefined
}))
复制代码
答案
[]
解析
这题比较简单,arr[10]=10,那么索引3到9位置上都是undefined,arr[3]等打印出来也确实是undefined,但是,这里其实涉及到ECMAScript版本不同对应方法行为不同的问题,ES6之前的遍历方法都会跳过数组未赋值过的位置,也就是空位,但是ES6新增的for of方法就不会跳过。
var name = 'World'
;(function () {
if (typeof name === 'undefined') {
var name = "Jack"
console.info('Goodbye ' + name)
} else {
console.info('Hello ' + name)
}
})()
复制代码
答案
Goodbye Jack
解析
这道题考察的是变量提升的问题,var声明变量时会把变量自动提升到当前作用域顶部,所以函数内的name虽然是在if分支里声明的,但是也会提升到外层,因为和全局的变量name重名,所以访问不到外层的name,最后因为已声明未赋值的变量的值都为undefined,导致if的第一个分支满足条件。
console.log(1 + NaN)
console.log("1" + 3)
console.log(1 + undefined)
console.log(1 + null)
console.log(1 + {})
console.log(1 + [])
console.log([] + {})
复制代码
答案
NaN、13、NaN、1、1[object Object]、1、[object Object]
解析
这道题考察的显然是+号的行为:
1.如果有一个操作数是字符串,那么把另一个操作数转成字符串执行连接
2.如果有一个操作数是对象,那么调用对象的valueOf方法转成原始值,如果没有该方法或调用后仍是非原始值,则调用toString方法
3.其他情况下,两个操作数都会被转成数字执行加法操作
var a={},
b={key:'b'},
c={key:'c'}
a[b]=123
a[c]=456
console.log(a[b])
复制代码
答案
45