JavaScript:学习笔记(4)——This关键字

以前这篇帖子是关于闭包的,但是我想弄明白的其实是This关键字。JavaScript的this和Java等面向对象语言中的this大不一样,bind()、call()和apply()函数更是将this的灵活度进一步延伸。

  • FunDebug:https://blog.fundebug.com/2017/05/17/javascript-this-for-beginners/

快速开始

如果对JavaScript的关键字this理解不够深刻,有时候会掉入意想不到的坑。在这里我们总结了几条通用规则来帮助你判断this到底指向什么。虽然没有囊括所有的情况,但日常大部分情况都可以使用这些规则来正确推断。

  1. this的值通常是由所在函数的执行环境决定,也就是说要看函数是如何被调用的;
  2. 同一个函数每一次调用,this都可能指向不同的对象;

全局对象(Global Object)

  打开Chrome浏览器开发者面板(Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J),并且输入:

  

  输出的结果是window,因为在全局作用域下,this指向全局对象。在浏览器中全局对象就是window对象。为了让你更加清楚理解为什么this会指向window对象,我们来看另外一个例子:

var myName = 'Brandon';

  我们可以通过在控制台输入myName来访问其值:

myName // 输出 'Brandon'

  其实,所有在全局定义的变量都绑定到window对象。我们来做如下测试:

window.myName
// 输出 'Brandon'
window.myName === myName
// 输出 true

现在我们将this放到函数内部,看看有何效果。

function test(){
return this;
}
test();

  你会发现this依然指向全局的window对象。因为this关键字没有处于一个声明的对象内部,默认指向全局window对象。这一点可能对于大部分初学者来说有点难以理解。当读完这篇文章,你就会豁然开朗。
注意:如果在strcit模式下,上面的例子中this为undefined。

声明的对象 (Declared Object)

  当this关键字在一个声明对象内部使用,其值会被绑定到调用该this的函数的最近的父对象。我们用例子来说明这个问题:

var person = {
first: 'John',
last: 'Smith',
full: function() {
console.log(this.first + ' ' + this.last);
}
};
person.full();
// 输出 'John Smith'

  在被声明的对象person中的full函数里面使用了this, 那么调用this的full函数的最近的父对象就是person, 因此,this指向person。

  我们再来分析一个更复杂的情况:

var person = {
first: 'John',
last: 'Smith',
full: function() {
console.log(this.first + ' ' + this.last);
},
personTwo: {
first: 'Allison',
last: 'Jones',
full: function() {
console.log(this.first + ' ' + this.last);
}
}
};

  打印结果,可以看到

person.full();
// 输出 'John Smith'
person.personTwo.full();
// 输出 'Allison Jones'

  你会发现满足我们前面所描述的规则:其值会被绑定到调用this的函数的最近的父对象。因为第二个full方法是包含在personTwo对象中的,所以this指向personTwo。

new关键字

  当使用new关键字构建一个新的对象,this会绑定到这个新对象。我们来看一个例子:

function Car(make, model) {
this.make = make;
this.model = model;
}

  根据第一条规则,你可能会推断this指向全局对象。但是如果我们使用new关键字来声明一个新的变量,Car函数中的this将会绑定一个新的空对象,然后初始化this.make和this.model的值。

var myCar = new Car('Ford', 'Escape');
console.log(myCar);
// 输出 Car {make: "Ford", model: "Escape"}

call, bind, 和apply

  我们可以显式的在call(),bind(),apply()中设置this的绑定对象。这三个函数很类似,但是我们需要注意它们微小的区别。我们来看一个例子:

function add(c, d) {
console.log(this.a + this.b + c + d);
}
add(3,4);
// 输出 NaN

  add函数输出NaN, 因为this.a和this.b未定义。现在我们引入对象,并且使用call()和apply()来调用:

function add(c, d) {
console.log(this.a + this.b + c + d);
}
var ten = {a: 1, b: 2};
add.call(ten, 3, 4);
// 输出 10
add.apply(ten, [3,4]);
// 输出 10

  当我们使用add.call(),第一个参数是this需要绑定的对象,剩下的是add函数本来的参数。因此,this.a指向ten.a,this.b指向ten.b。add.apply()也类似,除了第二个参数是一个数组,用于存储add函数的参数。bind()函数和call()类似,但是bind()函数不会立即被调用。bind()函数会返回一个函数,并且将this绑定好。

  具体的使用方法,可以查阅相关文献,目前我还没有接触过相关内容。

总结

  1. this的值通常是由当前函数的执行环境所决定;
  2. 在全局作用域,this指向全局对象 (window对象);
  3. 当使用new关键字声明,this指向新建对象;
  4. 我们可以使用call(), bind(), apply()来设置this;
  5. 箭头函数不会绑定this。 

JavaScript:学习笔记(4)——This关键字的更多相关文章

  1. JavaScript学习笔记–(new关键字)

    作用 是创建一个对象实例.这个对象可以是用户自定义的,也可以是一些系统自带的带构造函数的对象. 描述 创建一个对象类型需要创建一个指定了名称和属性的函数:其中这些属性可以指向它本身,也可以指向其他对象 ...

  2. JavaScript:学习笔记(7)——VAR、LET、CONST三种变量声明的区别

    JavaScript:学习笔记(7)——VAR.LET.CONST三种变量声明的区别 ES2015(ES6)带来了许多闪亮的新功能,自2017年以来,许多JavaScript开发人员已经熟悉并开始使用 ...

  3. JavaScript:学习笔记(6)——New运算符

    JavaScript:学习笔记(6)——New运算符 new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例. 快速开始 当你使用new关键字的时候,会 创建一个新的对象 将th ...

  4. JavaScript:学习笔记(5)——箭头函数=>以及实践

    JavaScript:学习笔记(5)——箭头函数=>以及实践 ES6标准新增了一种新的函数:Arrow Function(箭头函数).本文参考的链接如下: MDN箭头函数:https://dev ...

  5. Java程序猿的JavaScript学习笔记(汇总文件夹)

    最终完结了,历时半个月. 内容包含: JavaScript面向对象特性分析,JavaScript高手必经之路. jQuery源代码级解析. jQuery EasyUI源代码级解析. Java程序猿的J ...

  6. Java程序猿的JavaScript学习笔记(8——jQuery选择器)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  7. Java程序猿JavaScript学习笔记(2——复制和继承财产)

    计划和完成在这个例子中,音符的以下序列: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaSc ...

  8. Java程序猿的JavaScript学习笔记(3——this/call/apply)

    计划按例如以下顺序完毕这篇笔记: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScript ...

  9. Java程序猿JavaScript学习笔记(4——关闭/getter/setter)

    计划和完成这个例子中,音符的顺序如下: Java程序猿的JavaScript学习笔记(1--理念) Java程序猿的JavaScript学习笔记(2--属性复制和继承) Java程序猿的JavaScr ...

随机推荐

  1. windows 网络编程[转]

    利用winsock编写网络应用程序服务端的步骤简述如下WSAStartup 初始化网络编程库 socket 创建套接字 bind 指定地址.端口,绑定套接字 listen 进入监听状态 accept ...

  2. checkbox 自动换行

    把匹配的checkbox和文字用一对span标签包裹 并且给这个span标签加样式 display:inline-block <span style="display:inline-b ...

  3. 美柚“姨妈假”上头条,App事件营销怎么做

        近期,微博上有关"姨妈假"的话题异常火爆,事件源于厦门互联网企业美柚所推出的一项"奇葩福利"------女员工可向公司请姨妈假.此事经媒体报道.微博爆料 ...

  4. Erlang服务器内存吃紧的优化解决方法

    问题提出:服务器100万人在线,16G内存快被吃光.玩家进程占用内存偏高 解决方法: 第一步:erlang:system_info(process_count). 查看进程数目是否正常,是否超过了er ...

  5. ios math.h 常用数学函数

    1. 三角函数  double sin (double);正弦  double cos (double);余弦  double tan (double);正切  2 .反三角函数  double as ...

  6. 真正入坑git

    之前使用git一直用sourceTree可视化操作,直到今天刚好装不了sourceTree,所有只能苦逼的用git命令行了,真的一片空白,要做下笔记才行. 创建sshKey 创建ssh: ssh-ke ...

  7. ES6之路

    从工作到现在,虽然是PHP出身,一直都和JS形影不离,从JQ和原生处理页面,到后来被angular1的MVVM模式惊艳到,再到弃angular转战vue,到现在使用react,一路走来,跳坑无数,现在 ...

  8. iOSPOI检索详细总结

    iOS百度地图路径规划和POI检索详细总结 路径规划.png 百度地图的使用 百度地图API的导入网上说了许多坑,不过我遇到的比较少,这里就放两个比较常见的吧.坑一: 奥联WIFI_xcodeproj ...

  9. ch.poweredge.ntlmv2-auth

    <dependency> <groupId>ch.poweredge.ntlmv2-auth</groupId> <artifactId>ntlmv2- ...

  10. VC项目文件说明

    .dsp   项目参数配置文件,这个文件太重要,重点保护对象.. .dsw   工作区文件,重要性一般,因为它信息不我,容易恢复.   以下文件在项目中是可丢弃的,有些文件删除后,VC会自动生成的. ...