词法做用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则。 (函数做用域和块做用域)数组
JavaScript 中的做用域就是词法做用域,也就是静态做用域,由定义代码决定app
动态做用域彷佛暗示有很好的理由让做用域做为一个在运行时就被动态肯定的形式,而不是在写代码时进行静态肯定的形式函数
动态做用域并不关心函数和做用域是如何声明以及在何处声明的,只关心它们从何处调用。换句话说,做用域链是基于调用栈的,而不是代码中的做用域嵌套oop
ps:能够忽略下面这段话 :this
静态类型语言是指在编译时变量的数据类型便可肯定的语言,多数静态类型语言要求在使用变量以前必须声明数据类型,某些具备类型推导能力的现代语言可能可以部分减轻这个要求.
动态类型语言是在运行时肯定数据类型的语言。变量使用以前不须要类型声明,一般变量的类型是被赋值的那个值的类型spa
不要混淆概念噢 code
this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会建立一个活动记录(有时候也称为执行上下文)。这个记录会包
含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程当中用到对象
绑定规则: blog
1. 由new 调用?绑定到新建立的对象。
2. 由call 或者apply(或者bind)调用?绑定到指定的对象。
3. 由上下文对象调用?绑定到那个上下文对象。
4. 默认:在严格模式下绑定到undefined,不然绑定到全局对象。继承
1.默认绑定
function foo() { console.log( this.a ); } var a = 2; foo(); // 2
2.
function foo() { console.log( this.a ); } var obj = { a: 2, foo: foo }; var bar = obj.foo; // 函数别名! var a = "oops, global"; // a 是全局对象的属性 bar(); // "oops, global" 虽然bar 是obj.foo 的一个引用,可是实际上,它引用的是foo 函数自己,所以此时的 bar() 实际上是一个不带任何修饰的函数调用,所以应用了默认绑定。
3.
function foo() { console.log( this.a ); } function doFoo(fn) { // fn 其实引用的是foo fn(); // <-- 调用位置! } var obj = { a: 2, foo: foo }; var a = "oops, global"; // a 是全局对象的属性 doFoo( obj.foo ); // "oops, global" 参数传递其实就是一种隐式赋值,所以咱们传入函数时也会被隐式赋值,因此结果和上一 个例子同样
相似的例子:
function setTimeout(fn,delay) { // 等待delay 毫秒 fn(); // <-- 调用位置! }
fn若传入obj.fn 实际也发生隐式赋值
硬绑定的典型应用场景就是建立一个包裹函数,传入全部的参数并返回接收到的全部值:
function foo(something) { console.log( this.a, something ); return this.a + something; } var obj = { a:2 }; var bar = function() { return foo.apply( obj, arguments ); }; var b = bar( 3 ); // 2 3 console.log( b ); // 5
call和apply实际上就是调用fn(运行时绑定),将fn里面的this 绑定指向obj,运行fn arguments是fn参数组成的数组 fn.apply(obj,【arguments】)
call相似只不过fn的参数不是数组形式
function foo(something) { console.log( this.a, something ); return this.a + something; } // 简单的辅助绑定函数 function bind(fn, obj) { return function() { return fn.apply( obj, arguments ); }; } var obj = { a:2 }; var bar = bind( foo, obj ); var b = bar( 3 ); // 2 3 console.log( b ); // 5
箭头函数:
箭头函数最经常使用于回调函数中,例如事件处理器或者定时器: function foo() { setTimeout(() => { // 这里的this 在此法上继承自foo() console.log( this.a ); },100); } var obj = { a:2 }; foo.call( obj ); // 2
箭头函数会继承外层函数调用的this 绑定