动态作用域与this +apply和call +bind
词法作用域是一套关于引擎如何寻找变量以及会在何处找到变量的规则。 (函数作用域和块作用域)
JavaScript 中的作用域就是词法作用域,也就是静态作用域,由定义代码决定
动态作用域似乎暗示有很好的理由让作用域作为一个在运行时就被动态确定的形式,而不是在写代码时进行静态确定的形式
动态作用域并不关心函数和作用域是如何声明以及在何处声明的,只关心它们从何处调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套
ps:可以忽略下面这段话 :
静态类型语言是指在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型,某些具有类型推导能力的现代语言可能能够部分减轻这个要求.
动态类型语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型
不要混淆概念噢
this 的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。当一个函数被调用时,会创建一个活动记录(有时候也称为执行上下文)。这个记录会包
含函数在哪里被调用(调用栈)、函数的调用方法、传入的参数等信息。this 就是记录的其中一个属性,会在函数执行的过程中用到
绑定规则:
1. 由new 调用?绑定到新创建的对象。
2. 由call 或者apply(或者bind)调用?绑定到指定的对象。
3. 由上下文对象调用?绑定到那个上下文对象。
4. 默认:在严格模式下绑定到undefined,否则绑定到全局对象。
1.默认绑定
function foo() {
console.log( this.a );
}
var a = 2;
foo(); // 22.
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 ); // 5call和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 绑定
动态作用域与this +apply和call +bind的更多相关文章
- 深入理解javascript作用域系列第二篇——词法作用域和动态作用域
× 目录 [1]词法 [2]动态 前面的话 大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找.再加上this机制的干扰,使得变量查找极 ...
- JavaScript 使用词法作用域,没有动态作用域
function foo() { console.log( a ); } function bar() { var a = 3; foo(); } var a = 2; bar(); 上面的代码,控制 ...
- js call apply caller callee bind
call apply bind作用类似.即调用一个对象的一个方法,以另一个对象替换当前对象. call 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) ...
- 区分词法作用域(js)与动态作用域(精!)
在js学习中,词法作用域是必须要掌握的! 在这里,我将总结一下<你不知道的JS>一书中词法作用域的重点并分享给大家! 首先带来一段代码示例: function foo(){ console ...
- js之词法作用域与动态作用域
事实上JavaScript并不具有动态作用域,它只有词法作用域,简单明了,但是this机制某种程度上很像动态作用域 词法作用域:是一套引擎如何寻找变量以及会在何处找到变量的规则,它是定义在词法阶段的作 ...
- JavaScript深入之词法作用域和动态作用域
作用域 作用域是指程序源代码中定义变量的区域. 作用域规定了如何查找变量,也就是确定当前执行代码对变量的访问权限. JavaScript 采用词法作用域,也就是静态作用域. 静态作用域与动态作用域 因 ...
- Javascript中的词法作用域、动态作用域、函数作用域和块作用域(四)
一.js中的词法作用域和动态作用域 词法作用域也就是在词法阶段定义的作用域,也就是说词法作用域在代码书写时就已经确定了. js中其实只有词法作用域,并没有动态作用域,this的执 ...
- 词法作用域 vs 动态作用域
词法作用域 vs 动态作用域 链接:https://www.jianshu.com/p/cdebb5965000 scheme是一门采用词法作用域(lexical scoping)的lisp方言,这个 ...
- JavaScript 词法、静态、动态作用域初级理解
开始之前 由于本人也是JavaScript初学者,记录学习经过,怕以后会忘记. 对于JavaScript 初学者来说,最难的不是代码部分,而是对很多书籍中的术语的理解,大多时候想要理解一段JavaSc ...
随机推荐
- Impossible to load an image in xcassets on bundle
Impossible to load an image in xcassets on bundle up vote5down votefavorite 3 I need to include imag ...
- vfp 智能感知拓展应用
*======================================================================================== * * Versio ...
- Network Assistant (Alpha)版使用说明
Network Assistant (网络助手)使用说明 本软件是一款帮助同学方便Ip更改,小蝴蝶断线重连,一键wifi,定时关机的软件.它集成 ...
- 【JS】falsy与truthy
1.Falsy值,当进行逻辑判断时均为false(如!!false==false).六个Falsy值:false.undefined.null.正负0.NaN."". 2.其余所有 ...
- python自动化框架nose
python除了unittest,还有一款更快捷的nose,nose可以说是对unittest的一种简化吧 但是他不需要unittest那种必须有固有的格式,他只需要文件,类名,方法名等含有test就 ...
- RNN 入门学习资料整理
建议按序阅读 1. RNN的一些简单概念介绍 A guide to recurrent neural networks and backpropagation Deep learning:四十九(RN ...
- 由于OCR文件损坏造成Oracle RAC不能启动的现象和处理方法
v$cluster_interconnects 集群节点间通信使用的IP地址 错误信息 使用了公网进行连接 SQL> select * from v$cluster_interconnects; ...
- React(JSX语法)----JSX拼写
注意:For DOM differences,such as the inline style attribute,check here. // bad: it displays "FIrs ...
- C#的选择语句练习2
1.输入a,b,c三个数,计算一元二次方程ax²+bx+c的根:若a=0,则不是一元二次方程:△=b²-4ac,根的计算公式为-b±√b²-4ac/2a:若△=b²-4ac>0,则方程有两个不一 ...
- ffmpeg音频编码
在弄音频采集时,需要设置缓存的大小,如果只是简单的采集和直接播放PCM数据,缓存的大小一般不影响播放和保存. 但是,如果需要使用FFMpeg音频编码,这时,音频缓存的大小必须设置av_samples_ ...