var name = 'World!';
(function () {
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
在不作为参数传递的前提下 闭包中如何访问外部的 name?
var name = 'World!';
(function () {
var name = this.name;
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
}).call(this);
我能想到的是这么改了 但是和你的要求还是有小差距 传参了 不过一般都是 call(this)
这样写
好诡异的行为,代码改成下面那样就好了
var name = 'World!';
(function () {
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
// var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
#7 楼 @u1378130755 这个不是诡异 这个是 var 声明的预解析 虽然你是在 if 里面 var 的 但是他还是会提到顶部预解析 当你赋值的时候才有值 我写的那个只是应对你的写法 其实最好不要这么写的 这种写法是标准的反面教材...
#19 楼 @u1378130755 给你个传送门 不要自己琢磨了 你琢磨的不全对 覆盖只是一部分 http://www.nowamagic.net/librarys/veda/detail/1623
clojure 的 scope 是 function 的。就是有个 function,就有一个 scope。
scope 有点像一棵树(其实就是个属性结构,全局是跟)。假设一个变量出现在子树里面,比如 a,然后编译器看到 a 了,就开始找 a 是什么东西,在本 scope 里面找,如果有定义,那么直接得到值。如果没找到,就去他爹那找,一直找下去,如果到全局了,还没找到,就报错了。
var a = 10; #编译器记录了一个 a到10 的映射。
a+1;
编译器读到 a 的时候,就找 a 是什么,发现 a 是 10,赋值,进行运算。
因为后面有 var 进行了变量声明,所以匿名函数所访问的 name 是函数内声明的 name。即便声明语句实际上并没有被执行。比如
var name = "outer";
(function () {
console.log(name);
if (false) {
var name = "inner";
}
console.log(name);
})();
如果内部没有 var name 的话,其实可以直接拿到 name
var name = 'World!';
(function () {
console.log(name);
})();
所以我的建议是,不要重复变量名。
var name = 'World!';
var that=this;
(
function () {
console.log(that.name);
if (typeof name === 'undefined') {
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
我这样修改,似乎也不对啊,是用 node 执行的,若果是浏览器,this 会指向 window 全局环境,node 好像也应该有全局环境吧
#28 楼 @yfractal 我觉得你的子树与根不合适,我举个例子
var name = "The Window";
var object = {
name : "My Object",
getNameFunc : function(){
return function(){
return this.name;
};
}
};
alert(object.getNameFunc()());
按照你的逻辑,似乎应该是 My Object,事实上,看这个http://davidshariff.com/blog/what-is-the-execution-context-in-javascript/
@u1378130755 我有点过于随便了,而且是拿 scheme 往上套的(毕竟 js 的作者很大程度用了 scheme 的东西)。。。但应该大体是那个意思(也许差的很远。。。)。
这个是 this 的原因。在 JavaScript 中,那个东西叫了 方程,谁就是 this,如果没人叫的话,就是 window(其实叫 global 也差不多。。。)。
第一次,是 object call 了 getNameFunc,然后返回的是一个方程,随后,这个方程又被 call 了(第二括号),而这个时候已经没有 人叫这个方程了,所以 this 是 window,顾返回“The Window”.
按照 hisea 的说法应该是这样,在浏览器中是返回“My Object”的。 var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());
var that = this;
是较常用的一个有用法,因为 this 在 callback 中会改变,所以嵌套定义 function 的时候经常使用。
具体到你的例子, 我的意思是这样:
var namez = 'World!';
(function () {
var name = namez;
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();
//= require underscore
window.namespace = _.memoize(function(ns) {
ns = ns || '';
var parts = ns.split('.');
var current = window;
for (var i=0,len=parts.length; i < len; i++) {
var part = parts[i];
if (_.isUndefined(current[part])) {
current[part] = {};
}
current = current[part];
}
return current;
});
namespace("app.utility");
app.utility.namez = 'hello'
(function(){
console.log(app.utility.namez);
})()
希望有帮助
弄明白这个问题,首先你要理解 Javascript 作用域的问题,嵌套函数与被嵌套函数都有一着不同的作用链。函数在查找属性时首先会从作用链的第一个作用域查找属性,如果没有找到则继续去第二级作用域去找,到最后走到了全局环境(在浏览器中这个东西就是 window 对象)发现还是没有就会报错,这个过程是由下而上的。
看楼主的例子,总觉得是在 Coffeescript 里,如果不是的话可以这样:
var scp = { name: 'Foobar' };
(function () {
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
var name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
}).apply(scp);
不会污染全局……
变量声明提升 代码大概是这个意思
var name = 'World!';
(function () {
var name; //变量声明提升
console.log(name);
if (typeof name === 'undefined') {
console.log(typeof name);
console.log(name);
name = 'Jack';
console.log('Goodbye ' + name);
} else {
console.log('Hello ' + name);
}
})();