参考资料:>>>

this的指向

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

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

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

var name = "windowsName";
function a() {
var name = "Cherry";
console.log(this.name); // windowsName
console.log("inner:" + this); // inner: Window
}
a();
console.log("outer:" + this) // outer: Window

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

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

例 2:

var name = "windowsName";
var a = {
name: "Cherry",
fn : function () {
console.log(this.name); // Cherry
}
}
a.fn();

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

例 3:

var name = "windowsName";
var a = {
name: "Cherry",
fn : function () {
console.log(this.name); // Cherry
}
}
window.a.fn();

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

例 4:

var name = "windowsName";
var a = {
// name: "Cherry",
fn : function () {
console.log(this.name); // undefined
}
}
window.a.fn();

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

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

例 5:

var name = "windowsName";
var a = {
name : null,
// name: "Cherry",
fn : function () {
console.log(this.name); // windowsName
}
}
var f = a.fn;
f();

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

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

例 6:

var name = "windowsName";
function fn() {
var name = 'Cherry';
innerFunction();
function innerFunction() {
console.log(this.name); // windowsName
}
}
fn()

怎么改变this的指向

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

ES6中的箭头函数

ES6标准入门里面这么写

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

函数内部使用_this = this

var name = "windowsName";

var a = {

    name : "Cherry",

func1: function () {
console.log(this.name)
}, func2: function () {
var _this = this;
setTimeout( function() {
_this.func1()
},100);
}

}; 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. BFSDFS模板

    BFS模板: private static void bfs(HashMap<Character, LinkedList<Character>> graph,HashMap&l ...

  2. 从centos7镜像到搭建kubernetes集群(kubeadm方式安装)

    在网上看了不少关于Kubernetes的视频,虽然现在还未用上,但是也是时候总结记录一下,父亲常教我的一句话:学到手的东西总有一天会有用!我也相信在将来的某一天会用到现在所学的技术.废话不多扯了... ...

  3. HttpClient的CircularRedirectException解决办法

    解决方法: HttpGet httpGet = new HttpGet(" http://XXXX.XXX"); httpGet.getParams().setParameter( ...

  4. Spring Boot高频面试题:Spring Boot执行原理

    之前一篇文章Spring Boot快速入门文章中,我们已经体会到Spring Boot的神器,不再像之前Spring那样需要繁琐的XML,甚至几秒钟就能搭建出Spring的项目骨架.接下来我们简单分析 ...

  5. 迅速看一下jdk8

    一直在看java并发的感觉说的有点多,就看点简单的放松一下吧!这次来简单说一下jdk8,很久没用,都陌生了,仔细看看还挺有意思的,让我们大脑转化一个角度来写代码:因为我们现在平常大部分用jdk7写代码 ...

  6. MyBatis-Spring整合之方式1

    导入相关包:Spring包:Spring架包 MyBatis包:MyBatis架包 整合包:Mybatis-Spring整合包 编写实体类User,实体类的sql映射文件,映射内容如下: <?x ...

  7. BUUCTF-Web-Warm Up(CVE-2018-12613)

    题目(虽然是Warm up,但一点也不简单): 打开只有图片,源码里面提示了source.php 查看source.php: php代码里又提到了hint,去查看一下: 提示flag在如上图文件名里面 ...

  8. easyapi用法

    https://www.easyapi.com/api/?documentId=1773&themeId=

  9. linux 系统 grep 命令 摘录过滤特定的行

    1.grep ‘xxx’ filename  enter   其中xxx为要搜索的字符串 ,即可检索到含有 xxx的行. 2.grep 'xxx' filename  >newfilename ...

  10. SIMS(secondary ion mass spectroscopy)二次离子质谱

    1.仪器介绍 二次离子质谱(SIMS)是一种用于通过用聚焦的一次离子束溅射样品表面并收集和分析喷射的二次离子来分析固体表面和薄膜的组成的技术.SIMS是最灵敏的表面分析技术,元素检测限为百万分之几到十 ...