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模式下,上面的例子中thisundefined

声明的对象 (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, 那么调用thisfull函数的最近的父对象就是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.makethis.model的值

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

callbind, 和apply

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

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

  add函数输出NaN, 因为this.athis.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.badd.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. DedeCMS使用channelartlist循环,不能获取外部链接的解决办法

    Dede在制作下拉菜单时,可以使用channelartlist循环调用顶级栏目和子栏目,但该标签不能获取外部链接, 下拉菜单时一段代码搞定多个顶级栏目和子级栏目的同时输出. <div>   ...

  2. hdu 1541Stars

    题意:定义在某颗星星左下方的星星的个数表示该星星的水平,求出水平分别为为0...n-1的星星个数. 首先题目是按照y坐标升序输入的,设第第1,2...n个星星的横坐标依次为x1,x2,...xn.显然 ...

  3. Checkbox Text 重影问题的解决的方法

    Checkbox有个属性值 <CheckBox android:id="@+id/cb_reg_agree" style="@style/reg_checkbox_ ...

  4. Flak快速上手

    本文介绍如何上手 Flask . 这里假定你已经安装好了 Flask ,否则请先阅读< 安装>. 如果已安装好Flask,通过以下命令查看 一个简单的例子: from flask impo ...

  5. Linux多线程编程-信号量

    在Linux中.信号量API有两组.一组是多进程编程中的System V IPC信号量.另外一组是我们要讨论的POSIX信号量. 这两组接口类似,但不保证互换.POSIX信号量函数都已sem_开头,并 ...

  6. React15.6.0实现Modal弹层组件

    代码地址如下:http://www.demodashi.com/demo/12315.html 注:本文Demo环境使用的是我平时开发用的配置:这里是地址. 本文适合对象 了解React. 使用过we ...

  7. iOS 自己定义页面的切换动画与交互动画 By Swift

    在iOS7之前,开发人员为了寻求自己定义Navigation Controller的Push/Pop动画,仅仅能受限于子类化一个UINavigationController,或是用自己定义的动画去覆盖 ...

  8. VueJS构造器:new Vue({})

    构造器 每个 Vue.js 应用都是通过构造函数 Vue 创建一个 Vue 的根实例来启动的: var vm = new Vue({ // 选项 }) 属性与方法 每个 Vue 实例都会代理其 dat ...

  9. robotframework使用之 下拉框的选择

    选择下拉框有几种方式处理,首先在浏览器F12选择下拉框 1. F12后看见下拉框的源码是<option xxx> <select class="w_60" dat ...

  10. SQLAlchemy使用笔记--SQLAlchemy ORM(三)

    參考: http://docs.sqlalchemy.org/en/rel_1_0/orm/tutorial.html#eager-loading 预先载入 前面的代码,由于是lazy load.当我 ...