JavaScript 特殊理解

JS

var data = [];

for (var k = 0; k < 3; k++) {
debugger;
console.log("inner: "+k);
  data[k] = function () {
debugger;
    console.log("func: "+k);
  };
}
console.log("outer: "+k);
data[0](); // 3, 而不是0
data[1](); // 3, 而不是1
data[2](); // 3, 而不是2
15:06:59.381 VM66691:5 inner: 0
15:07:00.125 VM66691:5 inner: 1
15:07:01.292 VM66691:5 inner: 2
15:07:01.292 VM66691:11 outer: 3
15:07:01.492 VM66691:8 func: 3
15:07:01.700 VM66691:8 func: 3
15:07:01.905 VM66691:8 func: 3
15:07:01.929 undefined


eval()和Function构造不同

eval()可以干扰作用域链.
而Function()更安分守己些。
不管你在哪里执行 Function(),它只看到全局作用域。所以其能很好的避免本地变量污染。在下面这个例子中,eval()可以访问和修改它外部作用域中的变量,这是 Function做不来的(注意到使用Function和new Function是相同的)。

(function () {
   var local = 1;
   eval("local = 3; console.log(local)"); // logs "3"
   console.log(local); // logs "3"
}());

(function () {
   var local = 1;
   Function("console.log(typeof local);")(); // logs undefined
}());

ECMAScript只使用静态(词法)作用域(而诸如Perl这样的语言,既可以使用静态作用域也可以使用动态作用域进行变量声明)。

var x = 10;

function foo() {
  alert(x);//保持 x = 10
}

(function (funArg) {
  var x = 20;
  // 变量"x"在(lexical)上下文中静态保存的,在该函数创建的时候就保存了
  funArg(); // 10, 而不是20
})(foo);
技术上说,创建该函数的父级上下文的数据是保存在函数的内部属性 [[Scope]]中的

所有对象都引用一个[[Scope]]

这里还要注意的是:在ECMAScript中,同一个父上下文中创建的闭包是共用一个[[Scope]]属性的。也就是说,某个闭包对其中[[Scope]]的变量做修改会影响到其他闭包对其变量的读取:

var firstClosure;
var secondClosure;

function foo() {

  var x = 1;

  firstClosure = function () { return ++x; };
  secondClosure = function () { return --x; };

  x = 2; // 影响 AO["x"], 在2个闭包公有的[[Scope]]中

  alert(firstClosure()); // 3, 通过第一个闭包的[[Scope]]
}

foo();

alert(firstClosure()); // 4
alert(secondClosure()); // 3

发布了430 篇原创文章 · 获赞 415 · 访问量 925万+
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览