资讯专栏INFORMATION COLUMN

JavaScript之this

Yang_River / 646人阅读

摘要:的指向只和函数的调用位置方式有关,和函数声明的位置无关。全局浏览器全局这是中的默认绑定,在全局上下文中,会默认绑定到全局对象。同时上面四条绑定规则在箭头函数中不适用,使得的查找更可控。

本文共 1065 字,读完只需 4 分钟
概述

在 JAVA 中,this 的概念很透彻,就是指向当前对象(方法和属性的持有者),在编译的时候就能确定 this 指代,而由于 JavaScript 中 this 是动态绑定,或称为运行期绑定的,在绝大多数情况下,函数的调用方式决定了 this 的值,所以在 JS 中不能在定义时决定地定义 this 是哪个上下文对象。

this 的指向只和函数的调用位置(方式)有关,和函数声明的位置无关。

本文就从 this 应用场景调用方式的角度,解析 this 的用法。

首先,要知道,this 的作用是什么?

函数体内部,指代函数当前的运行上下文。
一、全局上下文

在全局上下文中,this 指向全局对象,在浏览器中指向 window,在 NodeJs 中指向 global。

var a = "全局";
console.log(this)  // 浏览器:window
console.log(this)  // nodejs:global
console.log(this.a)  // "全局"

这是 JS 中的默认绑定,在全局上下文中,this 会默认绑定到 全局对象。

二、函数声明

在非严格模式下,未加关键字 var 声明的变量,会成为全局对象下的属性,所以,此时
在严格模式下,this 将保持他进入执行上下文时的值,所以下面的 this 将会默认为 undefined。

function foo() {
    "use strict";
    console.log(this);
}

foo();  // undefined 严格模式

上述也是 JS 中 this 的默认绑定,在函数定义中,函数中的 this 会默认绑定到全局对象或者 undefined。

当函数作为对象里的方法被调用时,函数中 this 是调用该函数的对象。
function foo() {
    console.log("foo");
}

var obj = {
    this.bar = "bar";
    this.foo = foo;
}

obj.foo(); // "foo"

在调用位置,是 obj 对象调用了 foo 函数,此时 this 就指向了 obj 对象。

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

var obj2 =  {
    bar: "2",
    foo: foo
}

var obj1 = {
    bar: "1",
    obj2: obj2
}

obj1.obj2.foo()  // "2";

这是 JS 中 this 的隐式绑定,this 会隐式绑定到调用的最近一层上下文对象。

三、call & apply

其实在函数中,函数正确的调用应该是用 call, apply 函数的形式。

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

let obj = {
    bar: "1",
    foo: foo
}

obj.foo();  // `.` 点调用其实是语法糖

foo.call(obj)  // 1 正确的姿势
foo.apply(obj) // 1

这是 JS 中 this 的显式绑定,函数通过从 call 和 apply 函数可以显式指定函数的调用对象。

ES5 提供了一个 bind()方法:

let obj2 = {
    a: 2
}

let foo = function () {
    console.log(this.a);
}

let bar = foo.bind(obj2);
bar() // 2;

就是 JS 中 this 的硬绑定,bind() 函数会返回一个指定了调用对象的函数,返回的函数的被指定了 this 且 this 无法改变。

四、构造函数

当函数加上关键字 new 后,函数会变成一个构造函数,此时构造函数中的 this 指向即将创建的对象实例,同时对象实例会关联到构造函数的原型对象 prototype 上。

function Foo() {
    this.a = 3;
}

var obj = new Foo();

obj.a // 3
五、箭头函数

ES6 中,提供了函数定义的语法糖,让定义函数变得更简洁(没有 arguments, 没有原型)。同时上面四条绑定规则在箭头函数中不适用,使得 this 的查找更可控。

// 一般函数:
var a = 1;
var obj = {
  a: 2,
  say: function() {
    console.log(this.a)
  }
}
obj.say();  // console.log 打印值为 2

// 箭头函数
var a = 1;
var obj = {
  a: 2,
  say: () => {
    console.log(this.a)
  }
}
obj.say(); // 1   !!!

由于箭头函数定义时, obj {} 不是执行上下文,say 变量引用的箭头函数,其 this 是父级执行上下文,也就是全局上下文,所以 this.a 就是 全局变量 a: 1;

在箭头函数中,this 与封闭词法上下文的 this 保持一致,this 被永久绑定到了它最近一层非箭头函数的 this,而与函数的调用位置无关。

总结

在绝大多数情况下,函数的调用方式决定了 this 的值,但最终都指向了调用了它的那个上下文对象。

欢迎关注我的个人公众号“谢南波”,专注分享原创文章。

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

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

相关文章

  • JavaScript深入执行上下文

    摘要:深入系列第七篇,结合之前所讲的四篇文章,以权威指南的为例,具体讲解当函数执行的时候,执行上下文栈变量对象作用域链是如何变化的。前言在深入之执行上下文栈中讲到,当代码执行一段可执行代码时,会创建对应的执行上下文。 JavaScript深入系列第七篇,结合之前所讲的四篇文章,以权威指南的demo为例,具体讲解当函数执行的时候,执行上下文栈、变量对象、作用域链是如何变化的。 前言 在《Jav...

    gougoujiang 评论0 收藏0
  • JavaScript深入bind的模拟实现

    摘要:也就是说当返回的函数作为构造函数的时候,时指定的值会失效,但传入的参数依然生效。构造函数效果的优化实现但是在这个写法中,我们直接将,我们直接修改的时候,也会直接修改函数的。 JavaScript深入系列第十一篇,通过bind函数的模拟实现,带大家真正了解bind的特性 bind 一句话介绍 bind: bind() 方法会创建一个新函数。当这个新函数被调用时,bind() 的第一个参数...

    FingerLiu 评论0 收藏0
  • JavaScript深入new的模拟实现

    摘要:深入系列第十二篇,通过的模拟实现,带大家揭开使用获得构造函数实例的真相一句话介绍运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象类型之一也许有点难懂,我们在模拟之前,先看看实现了哪些功能。 JavaScript深入系列第十二篇,通过new的模拟实现,带大家揭开使用new获得构造函数实例的真相 new 一句话介绍 new: new 运算符创建一个用户定义的对象类型的实例或具...

    tianlai 评论0 收藏0
  • JavaScript深入继承的多种方式和优缺点

    摘要:深入系列第十五篇,讲解各种继承方式和优缺点。优点融合原型链继承和构造函数的优点,是中最常用的继承模式。寄生组合式继承为了方便大家阅读,在这里重复一下组合继承的代码组合继承最大的缺点是会调用两次父构造函数。 JavaScript深入系列第十五篇,讲解JavaScript各种继承方式和优缺点。 写在前面 本文讲解JavaScript各种继承方式和优缺点。 但是注意: 这篇文章更像是笔记,哎...

    JackJiang 评论0 收藏0
  • 学习JavaScriptthis,call,apply

    摘要:在全局对象中调用,自然读取的是全局对象的值构造器调用说明作为构造器调用时,指向返回的这个对象。最直观的表现就是,去看一些优秀框架的源代码时,不再是被绕的晕乎乎的。 学习起因: 在之前的JavaScript学习中,this,call,apply总是让我感到迷惑,但是他们的运用又非常的广泛。遂专门花了一天,来弄懂JavaScript的this,call,apply。中途参考的书籍也很多,以...

    wenhai.he 评论0 收藏0
  • JavaScript深入创建对象的多种方式以及优缺点

    摘要:深入系列第十四篇,讲解创建对象的各种方式,以及优缺点。也就是说打着构造函数的幌子挂羊头卖狗肉,你看创建的实例使用都无法指向构造函数这样方法可以在特殊情况下使用。 JavaScript深入系列第十四篇,讲解创建对象的各种方式,以及优缺点。 写在前面 这篇文章讲解创建对象的各种方式,以及优缺点。 但是注意: 这篇文章更像是笔记,因为《JavaScript高级程序设计》写得真是太好了! 1....

    Terry_Tai 评论0 收藏0

发表评论

0条评论

Yang_River

|高级讲师

TA的文章

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