JavaScript 的作用域和上下文对象this
从几个有意思的js题目最先
为何输出的不是f2?
`var scope = 'top'; var f1 = function() { console.log(scope); }; f1(); // 输出 top var f2 = function() { var scope = 'f2'; f1(); }; f2(); // 输出 top`
我还能接见closure,但this值转变
`function closure(arg){ var a ="closure"; console.log(a);//(1) closure console.log(this);//(2) obj对象 return function(){ console.log(a);//(4) closure console.log(arg); // (5) arg console.log(this);//(6) windowd对象 } } var obj ={ func:closure } function func () { setTimeout(obj.func("arg"),100); console.log("funcEnd");// (3)funcEnd } func()`
this会被绑定在某个对象上
`var b = "window.b" var funcFactory = function(){ var b ="func.b"; var obj ={ a:"obj.a", func:function(){ console.log(b) console.log(this.a); } } return obj; } var temp =funcFactory() var func = temp.func; temp.func();// 先涌现 func.b 后涌现obj.a func();// 先涌现func.b 后涌现 undefined`
4.函数实行完了,this绑定在window上
`function func(){ var a=1; setTimeout(function(){ console.log(a) },100); } func();// 1`
深度明白js静态作用域
js静态作用域
在第一段代码中很多人会天经地义的以为会打印出f2来,会说f2是个function,js是个以function为作用域分别,但是事变每每适得其反—末了打印出的是出人意料的top。大家都晓得js在实行之前会举行预处置惩罚(V8处置惩罚js还会先把它编程字节码),很多人只晓得在预处置惩罚的时刻会涌现var变量的提拔(es6的let就不会啦)和function一等国民的预先处置惩罚。但是却疏忽了作用域的处置惩罚— 函数作用域的嵌套关联是定义时决议的,而不是挪用时决议的,也就 是说,JavaScript 的作用域是静态作用域,又叫词法作用域,这是由于作用域的嵌套关联可 以在语法分析时肯定,而没必要比及运转时肯定。
this与作用域的谁在变化
起首让我们来明白下scope的观点—一段顺序代码中所用到的名字并不老是有用/可用的,而限制这个名字的可用性的代码局限就是这个名字的作用域。在网上老是有什么前端口试题问setTimeout或许setInterval内里的变量为何会转变,给出的答案永久是一模一样的作用域发作了变化,但是我们从第一段代码中我们就晓得js是一个在语法分析时作用域就已肯定了的。那究竟是什么发作了变化了呢?是this(学名上下文对象),this这个值在js中是很诡异的,等我有时间特地要拿出来说一讲,this这个值是会在运转时动态的发作变化的,比方call,apply,bind。至于setTimeout和setInterval一对兄弟,我想再分享一段代码来诠释下
function func(){ var a=1; setTimeout(function(){ console.log(a) },100); while(true){ a=2; } } func();
四段代码中你能够瞥见1,但在这段代码中你永久也不会再掌握台上发明1 的影子,由于只需没实行完func这个函数,js永久不会去事宜队列内里查询是不是有事宜发作。同时js的变量接纳也是在实行完一个函数后才实行的。
this和作用域的汇总引见
第三段代码的汇总运用啦,temp会从function中发挥obj对象,在我们挪用temp.func的时刻,this值会被绑定在obj这个对象上,显现console.log(b),由于b是从作用域中拿到的,所以在语法分析时就已给设定好啦,所以在掌握台上打印出“func.b”,在挪用this.a时,由于this被运转时绑定在obj对象上,所以会直接在obj上找(假如对象没有能够继续向上找真相链),当变量func去获得obj.func时,他只获得的是函数(不带包括它的对象),this自动会绑在window上,所以只能打印出b来(在语法分析时就已必定了接见哪一个变量),所以在window上找不到a这个属性,就致使了undefined的涌现。
总结
总而言之,作用域在语法分析时就已处置惩罚完啦,JavaScript 的作用域是静态作用域,在运转时只是this(上下文对象)在一向发作变化。也就是一个在运转前就完成分别(词法作用域Lexical Scope),一个是在运转中转变(类似于动态作用域Dynamic Scope),严厉意义上说JavaScript只是词法作用域。
js只要function来分别作用域。this的转变方式就大概有三种,第一种call,apply,bind要领(有点类似于c++的组合型配接器)this会被绑定在第一个参数对象,第二种事宜要领,setTimeout和setInterval会被绑定在全局对象上,像点击事宜之类的会被绑定在dom对象上,第三种obj.func接见对象里的function会被绑定在最内里的对象上,比方obj1.obj2.obj3.func会绑定在obj3上(有人会说function内里也能够写this的属性,对呀function也是继续自Object的呀,它自己自身就带上下文对象的)
作用域能够接见嵌套它的作用域值,而this是按着真相链去接见它父级对象,注重啦就如上例obj1.obj2.obj3.func,obj3虽然是obj2的属性,但不是继续于obj2的,它继续是经由过程它prototype属性来继续的,所以在obj3.func中this并不会去接见obj2的属性
跋文
不愿望今后有人会拿以上代码来口试或以以上代码去口试企业,这些学问晓得就好了,实战才能和对营业的把控才是顺序猿手艺的症结。
[1](http://www.cnblogs.com/bennman/archive/2013/09/08/3309024.html)