var obj = {};
(function(obj){
obj.m = function(){
console.log(ooo);
};
var ooo = {};
})(obj);
obj.m();//可以打印出 ooo {}
问题是这个ooo不是声明在obj.m这个方法后面吗,怎么可以打印出。本来以为是打印出underfined呢?
var obj = {};
(function(obj){
obj.m = function(){
console.log(ooo);
};
var ooo = {};
})(obj);
obj.m();//可以打印出 ooo {}
问题是这个ooo不是声明在obj.m这个方法后面吗,怎么可以打印出。本来以为是打印出underfined呢?
这跟变量提升没有关系,涉及到的知识是闭包和作用域。
闭包是一个函数,它能够记住创建它的那个作用域,并且在那个作用域外调用时仍然能够访问那个作用域里的变量。
分析你的代码:
var obj = {};
(function(obj){//作用域,命名为Scope
obj.m = function(){
//obj.m是一个声明在Scope中函数,记住了当前作用域Scope。
console.log(ooo);
};
var ooo = {};//声明在Scope中
})(obj);
obj.m();//当obj.m在Scope中调用时,根据闭包的定义,自然可以打印出 ooo {}
至于为什么不是打印undefined,是因为执行obj.m();
时,Scope中的ooo已经完成了赋值操作。
另一方面,没有报错Uncaught ReferenceError:ooo is not defined;也是能证明obj.m确实持有对Scope中的ooo的引用,也就是形成了闭包。
我看了一下你的评论,觉得我们理解的闭包概念不一样。我认为的闭包是obj.m,而你认为的闭包是(function(obj))(obj)这个IIFE。emmm,我觉得我是对的。
这样理解吧。obj.m = function(){}产生了一个闭包,因为方法体访问了ooo的引用。那么ooo这个引用显然是个动态的,根儿上来说就是个地址,这个地址指向的空间可能在定义obj.m的时候是个空的(undefined),但是随着程序的执行ooo被赋值了,地址指向的空间有东西了,自然也就能打印出东西了
大哥,当你执行obj.m()这个方法时,我ooo早就赋值了好吗。
除非这样写
var obj = {};
(function(obj){
obj.m = (function(){
console.log(ooo);
})();//这里改成自执行,这才是ooo还没赋值, 你那个是在代码末尾执行,我ooo已经赋了值了
var ooo = {};
})(obj);
var obj = {};//1
(function(obj){//2
obj.m = function(){//3
console.log(ooo);//6
};
var ooo = {};//4
})(obj);
obj.m();//5
13 回答13k 阅读
7 回答2.1k 阅读
3 回答1.3k 阅读✓ 已解决
6 回答1.2k 阅读✓ 已解决
2 回答1.4k 阅读✓ 已解决
3 回答1.3k 阅读✓ 已解决
6 回答1.1k 阅读
你说这段代码输出
undefined
还是aaaaa
只要调用的时候有值就行了