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. Hive修改行级别数据

    我们知道Hive0.14版本之前是不支持行级别的插入,更新,删除的,0.14版本之后可以通过修改相关配置得以支持,但是在不修改默认配置的情况下是不是完全没有办法呢?不是的,这里有个比较简单的方法,前提 ...

  2. JAVA入门[5]-初步搭建SpringMVC站点

    一.新建Module 1.新建Module,类型如下图所示: 2.为项目添加Spring框架支持,操作步骤如下: 首先在Module右键->Add Framework Support: 2.Sp ...

  3. 【Sqlsever系列】日期和时间

    1   概述 本文将集合MSDN简要概述Sqlserver中日期和时间函数. 2   具体内容 2.1  date and time data types 2.2  日期和时间功能 3   参考文献 ...

  4. Python爬虫(二十三)_selenium案例:动态模拟页面点击

    本篇主要介绍使用selenium模拟点击下一页,更多内容请参考:Python学习指南 #-*- coding:utf-8 -*- import unittest from selenium impor ...

  5. 《python参考手册(第四版)》【PDF】下载

    <python参考手册(第四版)>[PDF]下载链接: https://u253469.pipipan.com/fs/253469-230382222 内容介绍 本书是权威的Python语 ...

  6. iOS 用户密码 数字字母特殊符号设置 判断

    //直接调用这个方法就行 -(int)checkIsHaveNumAndLetter:(NSString*)password{ //数字条件 NSRegularExpression *tNumRegu ...

  7. Java I/O---输入与输出

    编程语言的I/O类库中常使用流这个抽象概念, 它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象. "流" 屏蔽了实际的I/O设备中处理数据的细节.Java类库中 ...

  8. 手动安装cloudera manager 5.x(tar包方式)详解

    官方共给出了3中安装方式:第一种方法必须要求所有机器都能连网,由于最近各种国外的网站被墙的厉害,我尝试了几次各种超时错误,巨耽误时间不说,一旦失败,重装非常痛苦.第二种方法下载很多包.第三种方法对系统 ...

  9. SVO环境搭建

    我是装了双系统,实验OS:Ubuntu14.04 Installation: Plain CMake (No ROS) 首先,建立一个工作目录比如:workspace,然后把下面的需要的都在该目录下进 ...

  10. java操作时间,将当前时间减一年,减一天,减一个月

    在Java中操作时间的时候,常常遇到求一段时间内的某些值,或者计算一段时间之间的天数 Date date = new Date();//获取当前时间 Calendar calendar = Calen ...