var a = {n: 1} var b = a a.x = a = {n: 2} console.log(a.n, b.n) //2 1 console.log(a.x, b.x) //undefined { n:2 }
这是一道经典面试题,看似简单,其实暗藏玄机。
至于对象赋值地址大家应该早已知道
关键在于第三句 a.x = a = {n: 2} 考察了两个基本点 :1 点语法和=语法的优先级 2 连等的赋值操作
分析:点语法比赋值优先级高,所以先执行点语法然后执行赋值,单纯你的以为a.x的点语法和离他最近的赋值=比较吗?(产生这想法的原因是大家都知道连等是从右往左赋值的,右边的等号在赋值的时候我a.x完全可以不用动)是连等的两个赋值等号比较,所以在a={ n : 2 } 之前就已经在a的空间里创建了一个x,并不是a={ n : 2 }之后才去创建。
详细的js连等介绍:http://www.cnblogs.com/xxcanghai/p/4998076.html
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var x = 10 function fn() { console.log(x) } function show(f) { var x = 20 f() } show(fn) //10
这道题从show(fn)来看,找到show函数传了一个fn函数,并执行fn,然后跟踪到fn的函数体,是要打印x
问题来了?打印的是全局的x还是show里面的x。乍一看因为执行fn的时候是在show里面调用的所以打印了20,实际上函数不管在哪调用,都要返回他原本声明的地方去执行,因为把函数当做实参传进去就是传的地址,如果是用arguments就是传的函数内容。
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var fn = function () { console.log(fn) } fn() // fn函数体 var obj = { fn2: function () { console.log(this.fn2) } } obj.fn2()
fn()打印比较简单,就是打印自己本身这个函数体
obj.fn2()调用了obj的方法,那么fn2中的this指向谁?在简单定义的对象中,方法中的this指向当前对象,非方法中的this指向window,所以打印的fn2函数体
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var c = 1; function c(c) { console.log(c); var c = 3; } console.log(c); // 1 c(2); // c is not a function
本题考查预解析:函数声明比var声明的更要前(本题没有用到,主要用到变量名提升在原地赋值),所以c早已变成1
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var name = 'World!' ;(function () { if (typeof name === 'undefined') { var name = 'Jack' console.log(name) } else { console.log(name) } })() // jack
本题考查函数自调用。再次强调一点,在js运行的预解析阶段只要有var 声明就要变量提前(千万别以为if是条件所以可能不在执行语句中,预解析还没执行呢,只是解析)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var a = 6 setTimeout(function () { console.log(0) alert(a) a = 666 }, 0) console.log(1) a = 66
本题考查主线程和异步的执行顺序,显然是主线程先执行,所以弹出66
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
function A () { } A.prototype.n = 1 var b = new A() A.prototype = { n: 2, m: 3 } var c = new A() console.log(b.n, b.m, c.n, c.m) // 1 undefined 2 3
本题考查的是先new 再改原型,之前new的实例会不会受影响(原理还是地址指向问题)
------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
var F = function(){} Object.prototype.a = function(){ console.log('a()') } Function.prototype.b = function(){ console.log('b()') } var f = new F() F.a() // a() F.b() // b() f.a() // a() f.b() // f.b is not a function
此题考查对函数也是对象在原型链上的提现:首先定义了一个函数F,相当于实例了一个函数即F.__proto__ === Function.prototype, Function.prototype === Object.prototype。
最后,考查沿着原型链查找,找不到返回undefined。
F.a()找到顶层Objecet,prototype上的方法,F.b()找到Function.prototype的方法
f.a()找到顶层Objecet,prototype上的方法(f也是一个对象所以顶层还是Objecet,prototype) ,但是f.b()在原型上找不到,注意此时f的原型不是Function.prototype,而是F.prototype,而顶层Object.prototype也找不到b方法所以报错