博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
this全面解析
阅读量:3959 次
发布时间:2019-05-24

本文共 3566 字,大约阅读时间需要 11 分钟。

this的绑定规则总共有下面5种:

  • 默认绑定(严格/非严格模式)
  • 隐式绑定
  • 显式绑定
  • new绑定
  • 箭头函数绑定

绑定规则

1.1 默认绑定

全局上下文默认this指向全局对象window, 严格模式下指向undefined

function foo() {
// 运行在严格模式下,this会绑定到undefined "use strict"; console.log( this.a );}var a = 2;foo(); // TypeError: Cannot read property 'a' of undefined// --------------------------------------function foo() {
// 运行 console.log( this.a );}var a = 2;(function() {
// 严格模式下调用函数则不影响默认绑定 "use strict"; foo(); // 2})();

1.2 隐式绑定

这种情况是直接调用。this相当于全局上下文的情况。

let name = 2222;let obj = {
name: 3333, a: function() {
console.log(this.name); // 2222 }}let func = obj.a;func();

1.3 显式绑定

通过call(..)或者 apply(..)方法。第一个参数是一个对象,在调用函数时将这个对象绑定到this。因为直接指定this的绑定对象,称之为显示绑定。

1.4 new绑定

如果函数调用前使用了 new 关键字, 则是调用了构造函数。 这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象:

// 构造函数:function myFunction(arg1, arg2) {
this.firstName = arg1; this.lastName = arg2;}// This creates a new objectvar a = new myFunction("Li", "Cherry");a.lastName; // "Cherry"

this指向

在 ES5 中,其实 this 的指向,始终坚持一个原理:this 永远指向最后调用它的那个对象

下面我们来看一个最简单的例子:

var name = "windowsName";function a() {
var name = "Libai"; console.log(this.name); // windowsName console.log("inner:" + this); // inner: Window}var b = {
name: "Libai", fn : function () {
console.log(this.name); // Libai }}a();b.fn(); // Libaiwindow.b.fn(); // Libai 最后调用它的对象仍然是对象 a

这个相信大家都知道为什么 log 的是 windowsName,我们看最后调用 a 的地方 a(),前面没有调用的对象那么就是全局对象 window,这就相当于是 window.a()

函数 fn 是对象 b 调用的,所以打印的值就是 b 中的 name 的值。是不是有一点清晰了呢~

再来看看下面这两个例子

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

读到现在了应该能够理解这是为什么了吧(o゚▽゚)o。

箭头函数

箭头函数的 this 始终指向函数定义时的 this,而非执行时。

箭头函数需要记着这句话:“箭头函数中没有 this 绑定,必须通过查找作用域链来决定其值,如果箭头函数被非箭头函数包含,则 this 绑定的是最近一层非箭头函数的 this,否则,this为 window”。

var name = "windowsName";var a = {
name : "Libai", func1: function () {
console.log(this.name) }, func2: function () {
setTimeout( () => {
this.func1() },100); }};a.func2() // Libai

使用 _this = this

如果不使用 ES6,那么这种方式应该是最简单的不会出错的方式了,我们是先将调用这个函数的对象保存在变量_this 中,然后在函数中都使用这个 _this,这样 _this 就不会改变了。

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

apply、call、bind

使用 apply、call、bind 函数也是可以改变 this 的指向的

apply 和 call 的区别

applycall基本类似,他们的区别只是传入的参数不同。

fun.call(this, arg1, arg2)    // 使用 call,参数列表fun.apply(this, [arg1, arg2]) // 使用 apply,参数数组var a = {
name : "Libai", fn : function (a,b) {
console.log(this.name, a + b) }}var b = a.fn;b.call(a, 1, 2) // Libai 3b.apply(a, [1, 2]) // Libai 3

bind 和 apply、call 区别

var a = {
name : "Libai", fn : function (a,b) {
console.log(this.name, a + b) }}var b = a.fn;b.bind(a, 1, 2)

我们会发现并没有输出,这是为什么呢,我们来看一下 MDN 上的文档说明:

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

所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:

var a = {
name : "Libai", fn : function (a,b) {
console.log(this.name, a + b) }}var b = a.fn;b.bind(a, 1, 2)() // Libai 3

觉得写得不错的话,请用你们发财的小手点个赞叭!

转载地址:http://usozi.baihongyu.com/

你可能感兴趣的文章
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Android 下 JNI 开发
查看>>
Mysql索引
查看>>
OGNL投影查询
查看>>
OGNL投影查询
查看>>
OGNL投影查询
查看>>
Redis之RDB和AOF持久化
查看>>
Redis之RDB和AOF持久化
查看>>
Servlet3.0
查看>>
Servlet3.0
查看>>
Servlet3.0
查看>>
SQL 语句的解析过程
查看>>
SQL 语句的解析过程
查看>>