本文共 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 的值,但最终都指向了调用了它的那个上下文对象。
欢迎关注我的个人公众号“谢南波”,专注分享原创文章。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。