2.2 .this的绑定规则
2.this的绑定规则
1.默认绑定
1 function foo( )
2 {
3 console.log(this.a);
4 }
5 var a=1;
6 foo(); //1
在代码中,foo()函数不带任何修饰的引用进行调用的,那么只能使用默认绑定。
2.隐式绑定
1 function foo1()
2 {
3 console.log( this.a );
4 }
5 var obj = {
6 a: 1,
7 foo: foo1
8 };
9 obj.foo(); //1
调用位置使用obj上下文来引用函数foo2,故可以说函数被调用时obj对象“拥有”或“包含”该函数foo2()。
那么foo2函数被调用时,确实加上了对obj的引用。当函数引用有上下文对象时,
隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
故上文中的this.a等同于obj.a。
PS1:对象属性引用链中只有上一层或者最后一层在调用位置中起作用。
1 function foo2()
2 {
3 console.log( this.a );
4 }
5 var obj2 = {
6 a: 2,
7 foo: foo2
8 };
9 var obj1 = {
10 a: 3,
11 obj2: obj2
12 };
13 obj1.obj2.foo(); //2
距离this最近的对象上下文时obj2,故this.a等同与obj2.a,同时等同于obj1.obj2.a。
PS2:隐式丢失
1 function foo3()
2 {
3 console.log( this.a );
4 }
5 var obj3 = {
6 a: 33,
7 foo: foo3
8 };
9 var bar=obj3.foo;
10 var a=3;
11 bar(); //3
这里的要点就是关注var bar=obj3.foo;
虽然bar只是obj3.foo的一个引用,但bar实际引用的时foo3()函数本身。
因此此时的bar()其实是一个不带任何修饰的函数调用,所以应用默认绑定。
PS2:隐式丢失(发生在函数调用时)。
1 function foo4( )
2 {
3 console.log(this.b);
4 }
5 function doFOO( fn )
6 {
7 var b=44;
8 fn();
9 }
10 var obj4={
11 b:10,
12 foo:foo4
13 };
14 var b=4;
15 doFOO(obj4.foo); //4
参数传递其实就是一个隐式赋值,故传入函数也会被隐式赋值。
所以结果与上面例子一致。
同理,这里传入的是自定义函数。即使传入的是内置函数,结果也是一样的。
PS3:如上所见,回调函数丢失this绑定是很常见的。
与此同时,另一种丢失情况更加出人意料:调用回调函数可能会修改this。
在一些流行的js库中,事件处理器经常会把回调函数的this绑定到DOM元素上。
3.显式绑定
显式绑定,即是通过call,apply等方法来强制绑定。
call与apply的第一个参数都是thisObj,表示this的指向。第二个参数,call是输入单个参数,apply是输入参数数组。多个参数时,后者性能更优。
1 function foo()
2 {
3 console.log( this.a );
4 }
5 var obj = {
6 a: 3
7 };
8 foo.call( obj ); //2 函数没有参数输入时,call只需要一个参数thisObj输入。
通过foo.call(),可以在调用foo时强制把它的this绑定到obj上。
PS1:“装箱”
如果thisObj参数传入的是一个原始值(简单数据类型),这个原始值会被转换成它的对象形式(如new String(..),new Boolean(..),或者new Number(..))。这通常称为“装箱”。
PS2:解决之前提出的丢失绑定问题。
1.硬绑定(显式绑定的一个变种)
1 function foo2()
2 {
3 console.log( this.a );
4 }
5 var obj2 = {
6 a: 3
7 };
8 var bar = function()
9 {
10 foo2.call( obj );
11 };
12 bar(); //3
13 setTimeout( bar, 100 ); //3
14
15 //切记,硬绑定的bar不可能在修改它的this。
16 bar.call( window ); //3
硬绑定的典型应用场景就是创建一个包裹函数,负责接收参数并返回值;
另一个使用方法就是创建一个可以重复应用的辅助函数:
1 function foo3( something )
2 {
3 console.log( this.d, something );
4 return this.d something;
5 }
6 function bind( fn, obj )
7 {
8 return function()
9 {
10 return fn.apply( obj, arguments );
11 };
12 }
13 var obj3 = {
14 d: 2
15 };
16 var bar3 = bind( foo3, obj3 );
17 var e = bar3( 3 ); //2 3
18 console.log( e ); //5
由于硬绑定是一个非常常用的模式,故ES5提供了一个内置方法bind,和上述用法类似。
1 function foo4( something )
2 {
3 console.log( this.a4, something );
4 return this.a4 something;
5 }
6 var obj4 = {
7 a4: 2
8 };
9 var bar4 = foo4.bind( obj4 );
10 var b4 = bar4( 5 ); //2 5
11 console.log( b4 ); //7
bind(..)会返回一个硬编码的新函数(切记,新函数),这会将指定的参数设置为this的上下文并调用原始函数。
2.API调用的“上下文”
第三方库的许多函数,以及JS语言和宿主环境(如浏览器环境)中许多内置函数,都提供了一个可选参数,通常称为“上下文(context)。
其作用与bind(..)类似,确保回调函数使用指定的this。
1 function foo5( el )
2 {
3 console.log( el, this.id );
4 }
5 var obj5 = {
6 id: "awesome"
7 };
8
9 //调用foo5(..)函数是将this绑定到obj。
10 [ "1", 2, 3 ].forEach( foo5, obj5 ); //console.log输出数字和字符串时,数字在前,字符串会有双引号;反之则没有。
11 // 1 awesome; 2 awesome; 3 awesome
4.new绑定
在此先纠正js中new与其他语言中new的区别。
在其它面向类语言中,”构造函数“是类中的一些特殊方法,使用new 初始化类时调用类中的构造函数。
在JS中,构造函数只是一些使用new操作符时被调用的函数。它们不属于某个类,也不会实例化一个类。
JS中使用new来调用函数,或者说发生构造函数调用时,会自动执行以下操作。
1.创建(或者说构造)一个全新的对象。
2.这个新对象会被执行[[Prototype]]链接。
3.这个新对象会绑定到函数调用的this。
4.如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。
1 function foo( a )
2 {
3 this.a = a;
4 }
5 var bar = new foo( 4 );
6 console.log( bar.a );
7
8 //使用new来调用foo(..)时,会构建一个新对象并将它绑定到foo(..)调用的this上,并将该对象返回给bar。
更多专业前端知识,请上 【猿2048】www.mk2048.com
2.2 .this的绑定规则相关推荐
- JavaScript中,this的绑定规则
对于 JavaScript 新手来说,this 是非常基础同时也难以理解的知识点. 比如下面的代码,this 指向就有三种方式. 在<你不知道的 JavaScript>一书中,我总算比较清 ...
- JavaScript this绑定规则
每个函数的this是在调用时被绑定的,完全取决于函数的调用位置. 1 默认绑定 function foo() {console.log(this); //输出:Window {postMessage: ...
- JavaScript中this指针的绑定规则
this指针的绑定规则 下面是对this指针绑定规则的整理,希望可以帮助到有需要的小伙伴. (1)默认绑定 this被定义在某个函数体中 该函数被独立调用,没有作为任何一个对象的方法时 这个this就 ...
- this四大绑定规则
谈到this绑定规则要先找到函数执行过程中的调用位置. 调用位置就是函数在代码中被调用的位置.这就涉及分析调用栈(就是为了到达当前执行位置所调用的所有函数).调用位置就在当前正在执行的函数的前一个调用 ...
- Erlang列表操作里面的变量绑定规则
2019独角兽企业重金招聘Python工程师标准>>> 原文如下: The scope rules for variables which occur in list compreh ...
- 这就是为什么我们需要在React的类组件中绑定事件处理程序
by Saurabh Misra 索拉·米斯拉(Saurabh Misra) 这就是为什么我们需要在React的类组件中绑定事件处理程序 (This is why we need to bind ev ...
- this指向undefined uiapp_JavaScript深入之史上最全5种this绑定全面解析
this的绑定规则总共有下面5种. 1.默认绑定(严格/非严格模式) 2.隐式绑定 3.显式绑定 4.new绑定 5.箭头函数绑定 1 调用位置 调用位置就是函数在代码中被调用的位置(而不是声明的位置 ...
- 【进阶3-1期】JavaScript深入之史上最全--5种this绑定全面解析
this的绑定规则总共有下面5种. 1.默认绑定(严格/非严格模式) 2.隐式绑定 3.显式绑定 4.new绑定 5.箭头函数绑定 1 调用位置 调用位置就是函数在代码中被调用的位置(而不是声明的位置 ...
- 无法对 null 引用执行运行时绑定_你真的懂this吗?聊聊默认绑定,隐式绑定,显示绑定,new绑定...
https://github.com/YvetteLau/Blog/issues/6 this关键字是JavaScript中最复杂的机制之一,是一个特别的关键字,被自动定义在所有函数的作用域中,但是相 ...
最新文章
- 百度Apollo无人车能力降维释放,打造智能汽车可以像拼乐高
- java-运算符以及简单运用
- 如何从SQL Server 中取得字段说明
- (力扣)中心扩散法求最长回文子串
- 【XSY1594】棋盘控制 概率DP
- mac系统虚拟机上的Linux系统的使用说明
- 管理新语:会议与问题的关系
- C语言程序设计 课程设计报告
- 学习c语言-----输出图形
- oppo手机解锁_oppo手机密码解锁大全【图文】
- 英语3500词(八)treat kids as adults主题(2022.1.20)
- 带你了解什么是产品经理,产品经理究竟做什么的【产品入门】
- 大数据级新闻去重实现 - 1.在线实时方案
- 报错:ImportError: Cannot load backend ‘TkAgg‘ which requires the ‘tk‘ interactive
- lisp 河道水面线计算_天然河道水面线计算程序
- 转:程序员风格的修真小说
- 音频信号处理(一)语音录制
- 2023最全兼职方式,(内含接单路径)
- 数字图像处理系列(二)---空间域图像增强-点运算
- python图片转文字easyocr_Python 实现OCR文字识别 TensorFlow 版本
热门文章
- android运行的线程中,android中线程是否运行在单独的进程中?
- cmakelists语法_CMakeList语法知识
- bzoj5147bzoj2121loj6701 字符串游戏
- Spring框架(二) ---- bean的歧义性
- Linux中的15个‘echo’ 命令实例
- luogu P1519 穿越栅栏 Overfencing
- 基于windows平台的命令行软件安装工具Chocolatey的安装
- 【坑】执行Consumer的时候发生java.net.UnknownHostException错误
- 【ASP.NET Web API教程】5.4 ASP.NET Web API批处理器
- GIS开源程序收集(转载)