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的绑定规则相关推荐

  1. JavaScript中,this的绑定规则

    对于 JavaScript 新手来说,this 是非常基础同时也难以理解的知识点. 比如下面的代码,this 指向就有三种方式. 在<你不知道的 JavaScript>一书中,我总算比较清 ...

  2. JavaScript this绑定规则

    每个函数的this是在调用时被绑定的,完全取决于函数的调用位置. 1 默认绑定 function foo() {console.log(this); //输出:Window {postMessage: ...

  3. JavaScript中this指针的绑定规则

    this指针的绑定规则 下面是对this指针绑定规则的整理,希望可以帮助到有需要的小伙伴. (1)默认绑定 this被定义在某个函数体中 该函数被独立调用,没有作为任何一个对象的方法时 这个this就 ...

  4. this四大绑定规则

    谈到this绑定规则要先找到函数执行过程中的调用位置. 调用位置就是函数在代码中被调用的位置.这就涉及分析调用栈(就是为了到达当前执行位置所调用的所有函数).调用位置就在当前正在执行的函数的前一个调用 ...

  5. Erlang列表操作里面的变量绑定规则

    2019独角兽企业重金招聘Python工程师标准>>> 原文如下: The scope rules for variables which occur in list compreh ...

  6. 这就是为什么我们需要在React的类组件中绑定事件处理程序

    by Saurabh Misra 索拉·米斯拉(Saurabh Misra) 这就是为什么我们需要在React的类组件中绑定事件处理程序 (This is why we need to bind ev ...

  7. this指向undefined uiapp_JavaScript深入之史上最全5种this绑定全面解析

    this的绑定规则总共有下面5种. 1.默认绑定(严格/非严格模式) 2.隐式绑定 3.显式绑定 4.new绑定 5.箭头函数绑定 1 调用位置 调用位置就是函数在代码中被调用的位置(而不是声明的位置 ...

  8. 【进阶3-1期】JavaScript深入之史上最全--5种this绑定全面解析

    this的绑定规则总共有下面5种. 1.默认绑定(严格/非严格模式) 2.隐式绑定 3.显式绑定 4.new绑定 5.箭头函数绑定 1 调用位置 调用位置就是函数在代码中被调用的位置(而不是声明的位置 ...

  9. 无法对 null 引用执行运行时绑定_你真的懂this吗?聊聊默认绑定,隐式绑定,显示绑定,new绑定...

    https://github.com/YvetteLau/Blog/issues/6 this关键字是JavaScript中最复杂的机制之一,是一个特别的关键字,被自动定义在所有函数的作用域中,但是相 ...

最新文章

  1. 百度Apollo无人车能力降维释放,打造智能汽车可以像拼乐高
  2. java-运算符以及简单运用
  3. 如何从SQL Server 中取得字段说明
  4. (力扣)中心扩散法求最长回文子串
  5. 【XSY1594】棋盘控制 概率DP
  6. mac系统虚拟机上的Linux系统的使用说明
  7. 管理新语:会议与问题的关系
  8. C语言程序设计 课程设计报告
  9. 学习c语言-----输出图形
  10. oppo手机解锁_oppo手机密码解锁大全【图文】
  11. 英语3500词(八)treat kids as adults主题(2022.1.20)
  12. 带你了解什么是产品经理,产品经理究竟做什么的【产品入门】
  13. 大数据级新闻去重实现 - 1.在线实时方案
  14. 报错:ImportError: Cannot load backend ‘TkAgg‘ which requires the ‘tk‘ interactive
  15. lisp 河道水面线计算_天然河道水面线计算程序
  16. 转:程序员风格的修真小说
  17. 音频信号处理(一)语音录制
  18. 2023最全兼职方式,(内含接单路径)
  19. 数字图像处理系列(二)---空间域图像增强-点运算
  20. python图片转文字easyocr_Python 实现OCR文字识别 TensorFlow 版本

热门文章

  1. android运行的线程中,android中线程是否运行在单独的进程中?
  2. cmakelists语法_CMakeList语法知识
  3. bzoj5147bzoj2121loj6701 字符串游戏
  4. Spring框架(二) ---- bean的歧义性
  5. Linux中的15个‘echo’ 命令实例
  6. luogu P1519 穿越栅栏 Overfencing
  7. 基于windows平台的命令行软件安装工具Chocolatey的安装
  8. 【坑】执行Consumer的时候发生java.net.UnknownHostException错误
  9. 【ASP.NET Web API教程】5.4 ASP.NET Web API批处理器
  10. GIS开源程序收集(转载)