资讯专栏INFORMATION COLUMN

[JavaScript 随笔] 关于 this 你必须知道这几点

邹强 / 735人阅读

摘要:关于中的坑大家都踩过。那这里的和是严格相等的。这里介绍的是通过创建对象时的。提示一下,数组对象的函数本身就是有这个功能的,也就是说可以达到要求。事件有两种记法,一个是也是类似,那么在中出现的表示触发该事件的元素,也就是。

TL;DR: this 指向调用该方法的对象,只有函数执行时,this 才有定义。

关于 JavaScript 中 this 的坑大家都踩过。像本文开头的这句话,道理你都懂,但是……所以这里就总结了几个 this 最常用的使用场景。

全局环境

在浏览器的全局环境中,this === window 。
但是,当使用了 "use strict"; 进入严格模式时,this === undefined 。

如果是在 nodejs 环境中,全局对象会更复杂一些,因为它有两种执行方式。一个是命令行方式,即输入

$ node

进入类似于浏览器的控制台一样的界面,可以逐行执行代码。那这里的 this 和 global 是严格相等的。但如果是

$ node program.js

这样执行一个文件的话,nodejs 会为每个文件创建一个自执行匿名函数的块,这里面的 this 并是全局对象 global 。但是,如果声明变量时没有加 var 的话,这些变量还是会加到 global 上去。

函数调用

函数中的 this 可能更常见一点吧。

function foo() {
  console.log(this.name);
}

如果直接判断这里的 this 是全局对象的话,就太冲动了(还记得最开始这句话吗?只有当函数调用时才能判断 this 真正引用的对象是什么)。

如果它作为一个全局函数【foo()】,或者闭包【return foo;】,又或者是回调函数【other(foo)】的话,那么它在执行时就是全局对象了。

还有三个我们经常遇到的方法可以改变 this 的引用,就是 call、apply 和 bind 。

foo.call(thisArg);

那么这里的 this 就指向了 thisArg,但当它为 null 或者 undefined,this 会指向全局对象。

还有一种函数调用是使用 new 关键字。

new foo();

这里的 this 指向的是构造出来的新对象。

那么其他情况就必然是 x.foo() 类似的调用方式了,看到这条语句的时候再去看 foo 的定义,它里面 this 引用的就是对象 x 。
数学学得好的话,可以反应过来 x 可以表示任何对象,比如 a,a.b,或者其他更复杂的表达式。

好,来测试一下,有如下代码

var o = {
  foo: function() { return this; }
};

function bar() {
  return o.foo;
}

console.log(bar()());

结果是什么?反正就两个选择,一是 this 指向全局对象,二是指向 o 。

原型

在上一篇文章 《继承的实现方式及原型概述》 中其实有提到过一部分原型方面的知识,那这里就稍微深入一点。

这里介绍的是通过 new 创建对象时的 this 。每个函数对象(用 function 关键字修饰的变量)自带 prototype 属性,在 prototype 上定义的属性都会继承给 this 。这些属性被每个实例共享,实例中会创建所有 prototype 上的属性,值为这些属性的引用。

文字一多心里难免烦烦的……

首先,这里通过 new 创建了两个实例,它们有相同的 prototype 。原型中的数据是创建在堆上的,所以继承下来的属性和方法都会指向同一个引用(左边的箭头)。

然后,在 this 上定义的属性和方法是创建在栈上的,所以这些属性和方法会有各自独立的内存区域(右边的箭头)。

假如在 this 上定义的变量与 prototype 上冲突了,那么 prototype 中的那个变量会“隐藏”起来。

如果有 child.foo = "tom"; 那么思考一下怎样才能让 child.foo 重新获得 prototype 中的 foo 值?

一种是可以直接 Parent.prototype.foo 就完事了。另外一种可以通过

delete child.foo; 
console.log(child.foo); // 重新获得 prototype 中的 foo 值

前者的缺点在于,假设 foo 是个函数的话,那么 Parent.prototype.foo() 时,其中的 this 指向的是 Parent.prototype,而不是 child 实例。

很多道理都很简单,那么再来考一下……

var slice = ___?

slice({"0": "a", "1": "b", "length": 2}) => ["a", "b"]

简单来说就是用一个表达式定义一个变量(函数),它可以将类数组对象(比如说 arguments)转化成数组。提示一下,数组对象的 slice 函数本身就是有这个功能的,也就是说 Array.prototype.slice.call(arguments) 可以达到要求。

DOM 事件

听说长篇大论不会受欢迎,但是我仔细想想还是得把这部分写下来。

事件有两种记法,一个是

el.addEventListener("event", handler);

attachEvent 也是类似,那么在 handler 中出现的 this 表示触发该事件的元素,也就是 el 。

另一种是

el.onevent = handler;

同样,handler 中的 this 还是 el 。

最后一个题……

var o = {
  foo: function() { return this; }
}

document.onload = o.foo;

请问,当 load 事件触发时,这里的 this 是什么?三个选择:o, window, document.

小结

从这里开始是“广告”时间了……

其实 this 的讨论可以展开很多,可能上面记的内容中有很多欠缺的地方,这个希望大家可以指正。

那我们的知识库总是会随着学习和努力慢慢扩大的,个人能力是一方面,花的精力是另一方面。只要肯静下心去琢磨,很多“网上各种人说这个难那个难”的知识(比如说闭包、原型,或者和知识面广度有关的,比如说数组中 slice 的高级用法等),花点时间总会搞懂的。

所以学习没有捷径,也没有培训班,有心就可以了。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/85839.html

相关文章

  • 继承的实现方式及原型概述 | JavaScript 随笔

    摘要:每一个对象直接量都是的子类,即构造函数中的构造函数与普通函数并没有什么两样,只不过在调用时,前面加上了关键字,就当成是构造函数了。由于没有传入变量,在调用的构造函数时,会出错这个问题可以通过一个空对象来解决改自。 showImg(https://segmentfault.com/img/bVmNZj); 对于 OO 语言,有一句话叫Everything is object,虽然 Ja...

    chenjiang3 评论0 收藏0
  • [JavaScript 随笔] 理解严格相等、非严格相等和隐式类型转换

    摘要:显然,相等判断是基于数字比较的,而条件判断是基于布尔值。严格相等严格相等的逻辑相对简单粗暴,如果类型不同,就不考虑隐式转换了,直接为假。 JavaScript 中大概有这几种 类型: undefined null string boolean number object function 之所以在 类型 上加了双引号,是因为严格来说,null 的类型是 object。但本文讨论的主...

    rickchen 评论0 收藏0
  • 一个JAVA WEB伪全栈的VUE入坑随笔:从登录开始(VUEX)

    摘要:此文章用于记录本人学习历程,有共同爱好者可加好友一起分享。从上周天,由于本周有公司篮球比赛,所以耽误两天晚上,耗时三个晚上勉强做了一个登录功能。这里的用户信息和登录状态都是直接取的中的用户信息进行属性值初始化。 此文章用于记录本人VUE学习历程,有共同爱好者可加好友一起分享。从上周天,由于本周有公司篮球比赛,所以耽误两天晚上,耗时三个晚上勉强做了一个登录功能。中间的曲折只有自己知道,有...

    Zack 评论0 收藏0
  • [译]JSX:硬币的另一面

    摘要:它不过是硬币的另一面。因此,既然我们能够接受与通过这种方式混合在一块儿,那么是时候让介入并向我们展示硬币的另一面了第三阶段的并不是一个激进的改变,是因为我们这个行业从一开始就注定和应该是在一起的。 React框架刚刚发布的时候,JSX颠覆了很多人的想法。习惯了HTML标签与JavaScript代码分离的前端工程师们,看到JSX大概都会不禁吐槽:这些奇怪的标签出现在JavaScript里...

    mudiyouyou 评论0 收藏0
  • 前端文档收集

    摘要:系列种优化页面加载速度的方法随笔分类中个最重要的技术点常用整理网页性能管理详解离线缓存简介系列编写高性能有趣的原生数组函数数据访问性能优化方案实现的大排序算法一怪对象常用方法函数收集数组的操作面向对象和原型继承中关键词的优雅解释浅谈系列 H5系列 10种优化页面加载速度的方法 随笔分类 - HTML5 HTML5中40个最重要的技术点 常用meta整理 网页性能管理详解 HTML5 ...

    jsbintask 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<