前端开发关于js闭包的一些常见的问题解析

宁波web前端开发招聘
前端开发招聘天津
web前端开发校园招聘

一、javascript 代码

function fun(n, o) {
    console.log(o)
    return {
        fun: function(m) {
            return fun(m, n)
        },
    }
}
var a = fun(0)
a.fun(1)
a.fun(2)
a.fun(3)
var b = fun(0)
    .fun(1)
    .fun(2)
    .fun(3)
var c = fun(0).fun(1)
c.fun(2)
c.fun(3)

答案为
a: undefined,0,0,0
b: undefined,0,1,2
c: undefined,0,1,1
思路解析:
var a = fun(0); a.fun(1); a.fun(2); a.fun(3);
1、fun(0)时,第一个参数n为0,第二个参数o未设置,console.log(o)为undefined,return值为:
{
fun:function(m){
return fun(m,n); //n为0
}
2、a.fun(1);m=1,代入上方return,得出新的return值为fun(1,0),执行得出console.log(0),return值为:
//fun(1,0) return值为:
{
fun:function(m){
return fun(m,n); //n为0
}
3、a.fun(2);m=2,同理代入上方return,得出新的return值为fun(2,0),执行得出console.log(0),return值为fun(3,0);
4、a.fun(3);m=3同理,代入上方return,得出新的return值为fun(3,0),执行得出console.log(0)。

var b = fun(0).fun(1).fun(2).fun(3);
1、与前面a一样,当执行到fun(0)时,第二个参数未设置,console.log(o)为undefined;
2、当执行到fun(0).fun(1)时,m为1,代入return,得出新的return值为fun(1,0),执行fun(1,0),console.log(0),return值为fun(1,1);
3、当执行到fun(0).fun(1).fun(2)时,m为2,代入return,得出新的return值为fun(2,1),执行fun(2,1),console.log(1),return值为(2,2)
4、当执行到fun(0).fun(1).fun(2).fun(3)时,m为3,代入return,得出新的return值为fun(3,2),执行fun(3,2),console.log(2);

var c = fun(0).fun(1); c.fun(2); c.fun(3);
1、当fun(0)时,与前面b一致,undefined;
2、当fun(0).fun(1)时,与前面b一致,console.log(0),得出新的return值为fun(1,1)
因此c.fun(2)就是fun(0).fun(1).fun(2),与前面b一致,console.log(1);
因此c.fun(3)就是fun(0).fun(1).fun(3),m=3,代入return,得出新的retrun:fun(3,1),得出结果console.log(1)

二、javascript 代码

for (var i = 0; i < 5; i++) {
    setTimeout(function() {
        console.log(i)
    }, 0)
}

答案为:5 5 5 5 5
思路解析::
这个定时器里面有个匿名函数且有闭包,要打印i此时调用了它外面的循环的i,当循环结束后才打印出i,所以i每次都是打印最后那个循环结束的最新值5

三、javascript 代码

var a = {}
var b = { key: ‘b’ }
var c = { key: ‘c’ }
a = 123 // toString = [object Object]
// console.log(a); //{[object Object]: 123}
a[c] = 456
console.log(a) //456

答案为:456
思路解析:
其实a变量中只有1个属性 [object Object](因为只有字符串才可以做属性名),它们在通过 [] 访问对象属性时,方括号中的表达式将会被求值并被通过调用它的toString方法转换成一个字符串.此时toString = [object Object],即这里的a=123和a[c]=456分别转换成了a[‘[object Object]’] = 123和a[‘[object Object]’] = 456,所以再次赋值就会被覆盖

四、javascript 代码

;(function() {
    var a = (b = 3)
})() //函数自调
console.log(‘a :’ + typeof a) //a :undefined
console.log(‘b : ‘ + typeof b) //b : number

答案为:a :undefined
b :number
思路解析:
因为在闭包中var声明的是局部变量,所以这里的a是局部变量,而b没有用var声明,所以在闭包中b自动变成全局变量,那因此打印的时候,由于a在这个函数的外面是没有声明而无法找到,而b在闭包里面b=3赋值了,所以输出b的类型是number

五、javascript 代码

function Foo() {
    getName = function() {
        alert(1)
    }
    return this
}
// 静态方法 只能通过 Foo.方法名()
Foo.getName = function() {
    alert(2)
}
Foo.prototype.getName = function() {
    alert(3)
}
var getName = function() {
    alert(4)
}
function getName() {
    alert(5)
}
Foo.getName() // 2
getName() // 4
Foo().getName() // 1
getName() // 1
new Foo.getName() // 2
new Foo().getName() // 3
new new Foo().getName() // 3

答案为:2 4 1 1 2 3 3
思路解析:
从题目来看,getName分别以变量,和函数变量的形式声明,涉及到变量声明提前。因此实际执行是:
function Foo() {
getName = function () { alert (1); };
return this;
}
var getName;//只提前变量声明
function getName() { alert (5);}//覆盖var的声明
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};
1、因此Foo.getName()调用时,首先访问静态属性,所以返回2;
2、getName();变量声明提前,函数声明提前,函数覆盖变量声明,所以返回4;
3、Foo().getName();执行第一个函数返回的this,Foo函数中赋值一个全局变量 getName=function(){alert(1)},当前作用域没有getName,因此会向上层寻找window,覆盖外面的getName的定义,返回一个1,。同时这时也改变了全局变量,this指向了window,相当于window.getName;
4、 getName();由于前面已经将全局变量给替换掉了,所以直接调用getName();
5、new Foo.getName()相当于 new(Foo.getName)(),这里注意运算符优先级,new一个(Foo.getName),即new了一个静态方法里的 Foo.getName对象,就返回了2 。这里运用了运算符优先级,其级别表示分别为:
圆括号()>成员访问>new带参数列表>函数调用>new不带参数列表>递增递减>逻辑运算符>一元加法减法>typeof>算数>位移>比较>in,instance>条件,赋值,逗号
6、(new Foo()).getName();是关于返回值的问题。在构造函数中,返回值可以没有返回值,有返回值的时候检查是不是引用类型,是基本类型等于undefined,实例里返回实例化对象,是引用类型的时候返回undefined,实例返回这个引用类型。这里返回了this是实例化对象,没有getName属性,通过原型链找到构造函数的原型对象为3;
7、new new Foo().getName();等价于new ((new Foo()).getName)(),所以也是返回3

六、javascript 代码

function ClassA() {
    var value = 4
    this.getValue = function() {
        return value
    }
    this.setValue = function(value) {
        this.value = value
    }
}
var classa = new ClassA()
document.write(classa.getValue()) // 4
classa.setValue(1) // 给对象classa添加了一个属性 value 他的是 1
document.write(classa.getValue()) // 4
document.write(classa.value) // 1

答案为:441
思路解析:
1、在这里的this.value其实是原型变量,在classA函数内部定义为classA.prototype.value,它 与 var value是两个不同的变量。
2、这里第一个和第二个classa.getValue()其实都是输出的var value=4这个值,而第三个classa.value其实输出的是this.value的值,因为这个值已经被setValue赋值为1了。
3、this.value和var value=4这个value是两个不同的变量, 而this.value和(classa.value和(classa.prototype.value是同一个变量

河源 前端开发 招聘
广州web前端开发招聘
2015百度招聘 深圳 web前端开发
» 本文来自:前端开发者 » 《前端开发关于js闭包的一些常见的问题解析》
» 本文链接地址:https://www.rokub.com/7793.html
» 您也可以订阅本站:https://www.rokub.com
赞(0)
64K

评论 抢沙发

评论前必须登录!