JavaScript中的this指针

作者: 小道小姐姐 | 来源:发表于2018-04-15 15:09 被阅读29次

JavaScript函数中的关键字this是自动获得的,因此,了解在不同的情况下this值指向的对象可以帮助我们减少程序中很多'莫名其妙'的bug.

全局上下文

在全局执行上下文中,this指向全局对象(browser: window, node: global),不管是严格模式还是非严格模式。

函数上下文

在函数中,this值取决与函数是如何调用的。

简单调用(不作为对象的方法或属性)

  • 非严格模式下:this值将会默认指向全局对象:
  function foo1() {
    return this;
  }
    
  console.log(foo1() === window); // true
  • 严格模式下:this值将会指向进入执行上下文时所设置的值,如果在执行上下文中没有设置this值,则会默认为undefined:
  function foo2() {
    'use strict';
    return this;
  }

  console.log(foo2() === undefined); // true

作为对象的方法

当函数作为对象的方法或属性时,它的this值将被设为调用该方法的对象:

  var o = {
    prop: 37,
    f() {
      return this.prop;
    }
  };
  console.log(o.f()); // 37

即使是通过对象字面量的方法将一个函数赋值给一个对象的属性,该行为也不会发生改变:

  var o = {prop: 37};
  function getProp() {
    return this.prop
  }
  o.f = getProp;
  
  console.log(o.f()); // 37

对象原型链中的this值

同样的,this仍然指向调用该函数的对象,尽管该函数位于该对象的原型链中:

  var o = {f: function() {return this.a + this.b;}};
  var p = Object.create(o);
  p.a = 1;
  p.b = 2;
  
  console.log(p.f()); //3

getter 或 setter 中的this

当函数作为属性的getter或者setter时,其中的this值指向该属性所在的对象:

  function sum() {
    return this.a + this.b + this.c
  }
  
  var o = {
    a: 1,
    b: 2,
    c: 3,
    get average() {
      return (this.a + this.b + this.c) / 3;
    }
  };
  Object.defineProperty(o, 'sum', {
    get: sum, enumerable: true, configurable: true
  });
  
  console.log(o.average, o.sum); // 2, 6

call方法 VS apply方法

call方法和apply方法都可以设置函数的this值,两者的第一个参数都是this值所指向的对象,区别在于call方法中的arguments是作为单个值传入fun.call(thisArg, arg1, arg2, ...),而apply方法中的arguments是作为数组传入func.apply(thisArg, [argsArray])

bind方法

ES5引入了Function.prototype.bind方法,调用f.bind(someObject)可以创建一个新的函数,该函数与f具有相同的函数体和作用域,但是新函数this值始终指向someObject。

  function f() {
    return this.a;
  }
  
  var g = f.bind({a: 'abc'});
  console.log(g()); // abc
  
  var h = g.bind({b: '123'}); // bind only works once
  console.log(h()); //abc 

注意到:通过bind方法获得的函数再次调用bind方法得到的新函数this值不会发生变化!

箭头函数

由于this值是自动获得的,以下hack的写法大家一定不陌生:

  {
    ...
    addAll: function addAll(pieces) {
      var self = this;
      _.each(pieces, function (piece) {
        self.add(piece);
      });
    },
    ...
  }

为了解决该问题,ES2015中引入了箭头函数语法糖,然而箭头函数的this值与一般函数的this值又有所区别,箭头函数的this值始终继承其外围作用域中的this值,在全局环境中将指向全局对象:

  // ES6
  {
    ...
    addAll: function addAll(pieces) {
      _.each(pieces, piece => this.add(piece));
    },
    ...
  } 

此处的addAll方法中的this值指向调用该方法的对象,而其内部的箭头函数的this值则继承自addAll方法的this值。

相关文章

  • JavaScript中的this指针

    JavaScript函数中的关键字this是自动获得的,因此,了解在不同的情况下this值指向的对象可以帮助我们减...

  • JavaScript中的this指针

    this是 JavaScript 中的一个关键字。它用在对象的方法中。 this 总是指向调用该方法的对象。 一、...

  • 函数传参的问题

    函数传参 值和引用 JavaScript 中没有指针,引用的工作机制也不尽相同。在 JavaScript 中变量不...

  • JavaScript闭包的理解

    前言 在JavaScript中,闭包对于JavaScript的意义无异于指针在c++中的意义。理解闭包是我们掌握J...

  • Javascript的对象拷贝

    在开始之前,我先普及一些基础知识。Javascript 的对象只是指向内存中某个位置的指针。这些指针是可变的,也就...

  • js this 的绑定和函数作用域

    this: 在 JavaScript 中,上下文对象就是 this 指针,即被调用函数所处的环境。上下文对象 的作...

  • oc之block模式

    block的是本质是对象。像javascript的闭包,函数里面的函数,java中的代码块,c中的函数指针等。就好...

  • WEB面试题总结

    模块一 JavaScript高级内功修炼 this指针/闭包/作用域 1.this指针详解 什么是this指向th...

  • 揭开 this & that 之迷

    新手在入门 JavaScript 的过程中,一定会踩很多关于 this 的坑,出现问题的本质就是 this 指针的...

  • 用JavaScript实现双向链表

    用JavaScript实现双向链表 前言 JavaScript本身是没有指针的,所以要实现链表的话没有现成的数据结...

网友评论

    本文标题:JavaScript中的this指针

    本文链接:https://www.haomeiwen.com/subject/jibdkftx.html