动态作用域与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(); // 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 绑定
动态作用域与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 ...
随机推荐
- Ansible-Tower快速入门-8.创建组织【翻译】
创建组织 首行,点击组织标签,组织中将包括有:用户,团队,项目,和清单等项,在tower的对象层级中,组织是最高级对象. 然后,点击增加按钮,如: 为所创建的组织键入一个简单的名称和描述,这些信息你在 ...
- 浅谈 HTTPS 和 SSL/TLS 协议的背景与基础
来自:编程随想 >> 相关背景知识 要说清楚 HTTPS 协议的实现原理,至少需要如下几个背景知识. 大致了解几个基本术语(HTTPS.SSL.TLS)的含义 大致了解 HTTP 和 ...
- The import javax.servlet cannot be resolved
在STS中,突然把配置的Tomcat删除,换另外一个Tomcat使用时,出现:The import javax.servlet cannot be resolved.这个错误可能是服务器自带的serv ...
- 苹果Home键恢复(无工具篇)
无工具法: 弹指神功.用手指轻轻弹Home,过了一阵子后可能会出现白色污垢,其后再重覆“弹”,直至正常为止.(亲测可用) 软件调试法.首先,打开任意一款应用程序,按住电源开关几秒钟,直到屏幕出现滑动关 ...
- iOS开发~CocoaPods使用详细说明
一.概要 iOS开发时,项目中会引用许多第三方库,CocoaPods(https://github.com/CocoaPods/CocoaPods)可以用来方便的统一管理这些第三方库. 二.安装 由于 ...
- css中的大小、定位、轮廓相关属性
css中的大小.定位.轮廓相关属性 1.通过height.width属性控制组件大小 height:高度,可以设置任何有效的距离值: width:宽度,可以设置任何有效的属性值: max-height ...
- C# 二维数组相关知识记录
//初始化一个数组 , ] { { , }, { , }, { , }, { , }, { , } }; //查某个字段的长度 print(name.GetLength()); //获得第一个字段的长 ...
- Linux下高cpu解决方案(转载)
昨天搞定了一个十万火急的issue,客户抱怨产品升级后系统会变慢和CPU使用率相当高,客户脾气很大,声称不尽快解决这个问题就退货,弄得我们 R&D压力很大,解决这个issue的任务分给了我,客 ...
- JAVA hashmap知识整理
HashMap和Hashtable的比较是Java面试中的常见问题,用来考验程序员是否能够正确使用集合类以及是否可以随机应变使用多种思路解决问题.HashMap的工作原理.ArrayList与Vect ...
- 【WEB前端】CSS常用选择器
1.1 标签选择器 就是用标签名来当做选择器. 1) 所有标签都能够当做选择器,比如body.h1.dl.ul.span等等 2) 不管这个标签藏的多深,都能够被选择上. 3) 选择的是所有的,而不是 ...