2.this的绑定规则

1.默认绑定

 function foo(  )
{
console.log(this.a);
}
var a=1;
foo(); //

在代码中,foo()函数不带任何修饰的引用进行调用的,那么只能使用默认绑定。

2.隐式绑定

 function foo1()
{
console.log( this.a );
}
var obj = {
a: 1,
foo: foo1
};
obj.foo(); //

调用位置使用obj上下文来引用函数foo2,故可以说函数被调用时obj对象“拥有”或“包含”该函数foo2()。
那么foo2函数被调用时,确实加上了对obj的引用。当函数引用有上下文对象时,
隐式绑定规则会把函数调用中的this绑定到这个上下文对象。
故上文中的this.a等同于obj.a。

PS1:对象属性引用链中只有上一层或者最后一层在调用位置中起作用。

 function foo2()
{
console.log( this.a );
}
var obj2 = {
a: 2,
foo: foo2
};
var obj1 = {
a: 3,
obj2: obj2
};
obj1.obj2.foo(); //

距离this最近的对象上下文时obj2,故this.a等同与obj2.a,同时等同于obj1.obj2.a。

PS2:隐式丢失

 function foo3()
{
console.log( this.a );
}
var obj3 = {
a: 33,
foo: foo3
};
var bar=obj3.foo;
var a=3;
bar(); //

这里的要点就是关注var bar=obj3.foo;
虽然bar只是obj3.foo的一个引用,但bar实际引用的时foo3()函数本身。
因此此时的bar()其实是一个不带任何修饰的函数调用,所以应用默认绑定。

PS2:隐式丢失(发生在函数调用时)。

 function foo4(  )
{
console.log(this.b);
}
function doFOO( fn )
{
var b=44;
fn();
}
var obj4={
b:10,
foo:foo4
};
var b=4;
doFOO(obj4.foo); //

参数传递其实就是一个隐式赋值,故传入函数也会被隐式赋值。
所以结果与上面例子一致。
同理,这里传入的是自定义函数。即使传入的是内置函数,结果也是一样的。

PS3:如上所见,回调函数丢失this绑定是很常见的。
与此同时,另一种丢失情况更加出人意料:调用回调函数可能会修改this。
在一些流行的js库中,事件处理器经常会把回调函数的this绑定到DOM元素上。

3.显式绑定
显式绑定,即是通过call,apply等方法来强制绑定。
call与apply的第一个参数都是thisObj,表示this的指向。第二个参数,call是输入单个参数,apply是输入参数数组。多个参数时,后者性能更优。

 function foo()
{
console.log( this.a );
}
var obj = {
a: 3
};
foo.call( obj ); //2 函数没有参数输入时,call只需要一个参数thisObj输入。

通过foo.call(),可以在调用foo时强制把它的this绑定到obj上。

PS1:“装箱”
如果thisObj参数传入的是一个原始值(简单数据类型),这个原始值会被转换成它的对象形式(如new String(..),new Boolean(..),或者new Number(..))。这通常称为“装箱”。

PS2:解决之前提出的丢失绑定问题。
1.硬绑定(显式绑定的一个变种)

 function foo2()
{
console.log( this.a );
}
var obj2 = {
a: 3
};
var bar = function()
{
foo2.call( obj );
};
bar(); //
setTimeout( bar, 100 ); // //切记,硬绑定的bar不可能在修改它的this。
bar.call( window ); //

硬绑定的典型应用场景就是创建一个包裹函数,负责接收参数并返回值;
另一个使用方法就是创建一个可以重复应用的辅助函数:

 function foo3( something )
{
console.log( this.d, something );
return this.d + something;
}
function bind( fn, obj )
{
return function()
{
return fn.apply( obj, arguments );
};
}
var obj3 = {
d: 2
};
var bar3 = bind( foo3, obj3 );
var e = bar3( 3 ); //2 3
console.log( e ); //

由于硬绑定是一个非常常用的模式,故ES5提供了一个内置方法bind,和上述用法类似。

 function foo4( something )
{
console.log( this.a4, something );
return this.a4 + something;
}
var obj4 = {
a4: 2
};
var bar4 = foo4.bind( obj4 );
var b4 = bar4( 5 ); //2 5
console.log( b4 ); //

bind(..)会返回一个硬编码的新函数(切记,新函数),这会将指定的参数设置为this的上下文并调用原始函数。

2.API调用的“上下文”
第三方库的许多函数,以及JS语言和宿主环境(如浏览器环境)中许多内置函数,都提供了一个可选参数,通常称为“上下文(context)。
其作用与bind(..)类似,确保回调函数使用指定的this。

 function foo5( el )
{
console.log( el, this.id );
}
var obj5 = {
id: "awesome"
}; //调用foo5(..)函数是将this绑定到obj。
[ "1", 2, 3 ].forEach( foo5, obj5 ); //console.log输出数字和字符串时,数字在前,字符串会有双引号;反之则没有。
// 1 awesome; 2 awesome; 3 awesome

4.new绑定
在此先纠正js中new与其他语言中new的区别。
在其它面向类语言中,”构造函数“是类中的一些特殊方法,使用new 初始化类时调用类中的构造函数。
在JS中,构造函数只是一些使用new操作符时被调用的函数。它们不属于某个类,也不会实例化一个类。

JS中使用new来调用函数,或者说发生构造函数调用时,会自动执行以下操作。
  1.创建(或者说构造)一个全新的对象。
  2.这个新对象会被执行[[Prototype]]链接。
  3.这个新对象会绑定到函数调用的this。
  4.如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象。

 function foo( a )
{
this.a = a;
}
var bar = new foo( 4 );
console.log( bar.a ); //使用new来调用foo(..)时,会构建一个新对象并将它绑定到foo(..)调用的this上,并将该对象返回给bar。

2.2 .this的绑定规则的更多相关文章

  1. 深入理解this机制系列第一篇——this的4种绑定规则

    × 目录 [1]默认绑定 [2]隐式绑定 [3]隐式丢失[4]显式绑定[5]new绑定[6]严格模式 前面的话 如果要问javascript中哪两个知识点容易混淆,作用域查询和this机制绝对名列前茅 ...

  2. js中this的绑定规则及优先级

    一.   this绑定规则 函数调用位置决定了this的绑定对象,必须找到正确的调用位置判断需要应用下面四条规则中的哪一条. 1.1 默认绑定 看下面代码: function foo() { cons ...

  3. 使用引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机绑定规则

    通过引用类型变量来访问所引用对象的属性和方法时,Java 虚拟机将采用以下绑定规则: 实例方法与引用变量实际引用的对象的方法进行绑定,这种绑定属于动态绑定,因为是在运行时由 Java 虚拟机动态决定的 ...

  4. this的四种绑定规则总结

    一.默认绑定 1.全局环境中,this默认绑定到window 2.函数独立调用时,this默认绑定到window console.log(this === window);//true functio ...

  5. JS中this的4种绑定规则

    this ES6中的箭头函数采用的是词法作用域. 为什么要使用this:使API设计得更简洁且易于复用. this即不指向自身,也不指向函数的词法作用域. this的指向只取决于函数的调用方式 thi ...

  6. .net core Web API参数绑定规则

    参数推理绑定 先从一个问题说起,微信小程序按照WebAPI定义的参数传递,Get请求服务器端可以正常接收到参数,但是Post请求取不到. Web API代码(.netcore 3.1)如下: [Htt ...

  7. JavaScript中this的绑定规则

    JavaScript中this的绑定规则 前言 我们知道浏览器运行环境下在全局作用域下的this是指向window的,但是开发中却很少在全局作用域下去使用this,通常都是在函数中进行使用,而函数使用 ...

  8. webapi frombody fromuri的参数绑定规则

    在WebAPI中,请求主体(HttpContent)只能被读取一次,不被缓存,只能向前读取的流. 举例子说明: 1. 请求地址:/?id=123&name=bob 服务端方法: void Ac ...

  9. MyBatis参数绑定规则及原理分析

    MyBatis参数的传递有几种不同的方法,本文通过测试用例出发,对其中的方式进行总结和说明,并对其部分源码进行分析. 一.测试用例(环境参考之前博客SSM接口编程一文 http://www.cnblo ...

随机推荐

  1. 自学Python2.6-深浅拷贝

    Python 深浅拷贝 一.深浅拷贝- 数字.字符串 对于 数字 和 字符串 而言,赋值.浅拷贝和深拷贝无意义,因为其永远指向同一个内存地址. import copy n1=123 n2=n1 # # ...

  2. 【JMeter】JMeter代码里若有外部自定义方法调用需要写进方法体里,否则报错

  3. jemeter——badboy导入的jmx文件自带元件解析

    线程组设置与解析 含义:1秒启动100个线程,每个线程循环调用20次请求  (包括FTP请求.Java请求.http请求,根据你提交的请求而定) delay thread creation until ...

  4. iOS OC Swift3.0 TableView 中tableviewcell的线左边不到边界

    Swift 3.0 func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt index ...

  5. iOSXML & JSON 简介

    XML & JSON 简介 •JSON –作为一种轻量级的数据交换格式,正在逐步取代XML,成为网络数据的通用格式 –基于JavaScript的一个子集 –易读性略差,编码手写难度大,数据量小 ...

  6. 我与 windows kernel 的一段时光

    写在前面 本科毕业设计是实现一个基于 windows 的透明加密过滤系统.由此对 windows kernel development,尤其是 file system 进行过较为深入的探索.对于防终止 ...

  7. Android Activity生命周期详细解析

    概况 讲Android Activity那怎么都绕不过这张图,这篇文章也是围绕这幅图详细分析. 背景 假设这是你的APP,以此为背景,下面的每个part请结合上图理解. #Case 1 当按下app启 ...

  8. androidSD卡操作

    1.获取SD卡目录:File file = Environment.getExternalStorageDirectory(); 2.获取SD卡路径:String path = Environment ...

  9. bzoj 3571: [Hnoi2014]画框

    Description 小T准备在家里摆放几幅画,为此他买来了N幅画和N个画框.为了体现他的品味,小T希望能合理地搭配画与画框,使得其显得既不过于平庸也不太违和.对于第 幅画与第 个画框的配对,小T都 ...

  10. TxDragon的训练5

    Solution 代码:由乃: //MADE BY QT666 #include<iostream> #include<cstdio> #include<algorith ...