参考资料:>>>

this的指向

在 ES5 中,其实 this 的指向,始终坚持一个原理:

  1. this 永远指向最后调用它的那个对象

下面我们来看一个最简单的例子:(例子均来自参考资料中的经典例子)
例 1:

  1. var name = "windowsName";
  2. function a() {
  3. var name = "Cherry";
  4. console.log(this.name); // windowsName
  5. console.log("inner:" + this); // inner: Window
  6. }
  7. a();
  8. console.log("outer:" + this) // outer: Window

这个相信大家都知道为什么 log 的是 windowsName,因为根据刚刚的那句话“this 永远指向最后调用它的那个对象”,我们看最后调用 a 的地方 a();,前面没有调用的对象那么就是全局对象 window,这就相当于是 window.a()

注意,这里我们没有使用严格模式,如果使用严格模式的话,全局对象就是 undefined,那么就会报错 Uncaught TypeError: Cannot read property 'name' of undefined

例 2:

  1. var name = "windowsName";
  2. var a = {
  3. name: "Cherry",
  4. fn : function () {
  5. console.log(this.name); // Cherry
  6. }
  7. }
  8. a.fn();

在这个例子中,函数 fn 是对象 a 调用的,所以打印的值就是 a 中的 name 的值。

例 3:

  1. var name = "windowsName";
  2. var a = {
  3. name: "Cherry",
  4. fn : function () {
  5. console.log(this.name); // Cherry
  6. }
  7. }
  8. window.a.fn();

这里打印 Cherry 的原因也是因为刚刚那句话“this 永远指向最后调用它的那个对象”,最后调用它的对象仍然是对象 a。

例 4:

  1. var name = "windowsName";
  2. var a = {
  3. // name: "Cherry",
  4. fn : function () {
  5. console.log(this.name); // undefined
  6. }
  7. }
  8. window.a.fn();

这里为什么会打印 undefined 呢?这是因为正如刚刚所描述的那样,调用 fn 的是 a 对象,也就是说 fn 的内部的 this 是对象 a,而对象 a 中并没有对 name 进行定义,所以 log 的 this.name 的值是 undefined

这个例子还是说明了:this 永远指向最后调用它的那个对象,因为最后调用 fn 的对象是 a,所以就算 a 中没有 name 这个属性,也不会继续向上一个对象寻找 this.name,而是直接输出 undefined

例 5:

  1. var name = "windowsName";
  2. var a = {
  3. name : null,
  4. // name: "Cherry",
  5. fn : function () {
  6. console.log(this.name); // windowsName
  7. }
  8. }
  9. var f = a.fn;
  10. f();

这里你可能会有疑问,为什么不是 Cherry,这是因为虽然将 a 对象的 fn 方法赋值给变量 f 了,但是没有调用,再接着跟我念这一句话:“this 永远指向最后调用它的那个对象”,由于刚刚的 f 并没有调用,所以 fn() 最后仍然是被 window 调用的。所以 this 指向的也就是 window。

由以上五个例子我们可以看出,this 的指向并不是在创建的时候就可以确定的,在 es5 中,永远是this 永远指向最后调用它的那个对象

例 6:

  1. var name = "windowsName";
  2. function fn() {
  3. var name = 'Cherry';
  4. innerFunction();
  5. function innerFunction() {
  6. console.log(this.name); // windowsName
  7. }
  8. }
  9. fn()

怎么改变this的指向

  • 使用 ES6 的箭头函数
  • 在函数内部使用 _this = this
  • 使用 applycallbind
  • new 实例化一个对象

ES6中的箭头函数

ES6标准入门里面这么写

  • 函数体内的this对象就是定义时所在的对象,而不是使用时所在的对象。
  • 不可以当作构造函数。也就是说,不可以使用new命令,否则会抛出一个错误。
  • 不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用rest参数代替。
  • 不可以使用yield命令,因此箭头函数不能用作Generator。

函数内部使用_this = this

  1. var name = "windowsName";
  2.  
  3. var a = {
  4.  
  5. name : "Cherry",

  6. func1: function () {
  7. console.log(this.name)
  8. },
  9.  
  10. func2: function () {
  11. var _this = this;
  12. setTimeout( function() {
  13. _this.func1()
  14. },100);
  15. }

  16. };
  17.  
  18. a.func2() // Cherry
这个例子中,在 func2 中,首先设置 var _this = this;,这里的 this 是调用 func2 的对象 a,为了防止在 func2 中的 setTimeout 被 window 调用而导致的在 setTimeout 中的 this 为 window。我们将 this(指向变量 a) 赋值给一个变量 _this,这样,在 func2 中我们使用 _this 就是指向对象 a 了。

使用apply,call,bind

详细例子可查看参考资料。这里我列举一下我的看法

apply

fun.apply(a,b);

a代表要fun函数在运行的时候指定的this值;

b代表要传入的数组或者类数组对象

call

fun.call(a[,b1[,b2[,......]]])

a代表fun函数在运行的时候指定的this值;

b代表要传入的若干个参数列表

bind

bind()方法创建一个新的函数,当被调用时,将其this关键字设置为提供的值,在调用新函数时,在任何提供之前提供一个给定的参数序列。

跟call类似,只不过需要在后面加上一个();

例如:b.bind(a,1,2)()

ES5中的this的更多相关文章

  1. ES5中新增的Array方法详细说明

    一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如下: forEach (j ...

  2. ES5中数组新增的方法说明

    一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块,我们可能就不需要去有板有眼地for循环了. ES5中新增了写数组方法,如forEach (js v ...

  3. 《JS权威指南学习总结--7.9 ES5中的数组方法》

    内容要点: ES5中定义了9个新的数组方法来遍历.映射.过滤.检测.简化和搜索数组. 概述:首先,大多数方法的第一个参数接收一个函数,并且对数组的每个元素(或一个元素)调用一次该函数. 如果是稀疏数组 ...

  4. Es5中的类和静态方法 继承

    Es5中的类和静态方法 继承(原型链继承.对象冒充继承.原型链+对象冒充组合继承) // es5里面的类 //1.最简单的类 // function Person(){ // this.name='张 ...

  5. Typescript 学习笔记四:回忆ES5 中的类

    中文网:https://www.tslang.cn/ 官网:http://www.typescriptlang.org/ 目录: Typescript 学习笔记一:介绍.安装.编译 Typescrip ...

  6. ES6中的类继承和ES5中的继承模式详解

    1.ES5中的继承模式 我们先看ES5中的继承. 既然要实现继承,首先我们得要有一个父类. Animal.prototype.eat = function(food) { console.log(th ...

  7. ES5中的类与继承

    最近在重新复习TypeScript,看到类这块的时候自然会和ES5中的类写法进行对比加深印象. 发现ES5的类与继承一些细节还是挺多的,时间久了容易忘记,特此记录下. 首先是ES5的类定义,这没什么好 ...

  8. ES5中新增的forEach等新方法的一些使用声明

    转载地址:http://www.zhangxinxu.com/wordpress/?p=3220 一.前言-索引 ES5中新增的不少东西,了解之对我们写JavaScript会有不少帮助,比如数组这块, ...

  9. ES6中。类与继承的方法,以及与ES5中的方法的对比

    // 在ES5中,通常使用构造函数方法去实现类与继承 // 创建父类 function Father(name, age){ this.name = name; this.age = age; } F ...

随机推荐

  1. oracle创建、删除索引等操作

    1.创建索引 create index 索引名 on 表名(列名); 2.删除索引 drop index 索引名; 3.创建组合索引 create index 索引名 on 表名(列名1,,列名2); ...

  2. C 语言实例 - 约瑟夫生者死者小游戏

    30 个人在一条船上,超载,需要 15 人下船. 于是人们排成一队,排队的位置即为他们的编号. 报数,从 1 开始,数到 9 的人下船. 如此循环,直到船上仅剩 15 人为止,问都有哪些编号的人下船了 ...

  3. 线上BUG定位神器(阿尔萨斯)-Arthas2019-0801

    1.下载这个jar 2.运行这个jar 3.选取你需要定位的问题应用进程 然后各种trace -j xx.xxx.xx.className methodName top -n 3 这个后面要补充去看, ...

  4. 03-书城bean类中的id缺少get属性

    错误:id属性不可读 解决方法: 测试了删除的整个流程,dao-service-servlet ,数据库也能正常测试 想不出来为什么会bean类报错 后来仔细一看id的get属性不知道什么时候被误删了 ...

  5. Linux安装Redis服务

    下载:wget  http://download.redis.io/releases/redis-5.0.5.tar.gz 解压:tar -zxvf redis-5.0.5.tar.gz 进入redi ...

  6. celery 使用 - 3

    # celery 使用 1.broker 2.基础案例 使用redis作为broker和brokend. 创建tasks.py # tasks.py di = 'redis://:****@local ...

  7. springboot @Configuration @bean注解作用

    @Configuration注解可以达到在Spring中使用xml配置文件的作用 @Bean就等同于xml配置文件中的<bean> 在spring项目中我们集成第三方的框架如shiro会在 ...

  8. 1、安装GPIO Zero(Installing GPIO Zero)

    学习目录:树莓派学习之路-GPIO Zero 官网地址:http://gpiozero.readthedocs.io/en/stable/installing.html 环境:UbuntuMeta-1 ...

  9. Spring_002 依赖注入方式实现

    继续写我们的第一个Spring程序,这次我们使用依赖注入的方式实现程序 第一步,建立我们的Spring_002程序,并在程序中添加BookDao.java.BookDaoImpl.java.BookS ...

  10. FFmpeg + php 视屏转换

    什么是FFmpeg? FFmpeg是一个开源免费跨平台的视频和音频流方案,属于自由软件,采用LGPL或GPL许可证(依据你选择的组件).它提供了录制.转换以及流化音视频的完整解决方案.它包含了非常先进 ...