你真的了解this指向吗?

javascript/jquery

浏览数:307

2019-4-19

前言

相信很多人都对JavaScript中的this指向问题一知半解,所以今天就来详细看看它到底是怎么判断的。

一. 先看几道题

  var length = 10;
    function fn() {
      console.log(this.length);
    }

  var obj = {
    length: 5,
    method: function(fn) {
      fn();
      arguments[0]();
    }
  };

  obj.method(fn, 1); // 10 2
  var name = 'window';

  function f1() {
    var name = 'f1';
    return function f2() {
      var name = 'f2';
      console.log(this.name);
    }
  }

  var foo = f1();
  var bar = {
    name: 'bar',
    foo: foo
  };

  foo(); // window
  bar.foo(); // bar
var name = 'window';
  var bar = {
    name: 'bar',
    foo: function () {
      var self = this;
      console.log(this.name);
      console.log(self.name);
      (function () {
        console.log(this.name);
        console.log(self.name);
      })()
    }
  };

  bar.foo(); // bar bar window bar
  var name = 'window';

  function f1() {
    var name = 'f1';
    return () => {
      var name = 'f2';
      console.log(this.name);
    }
  }

  var foo = f1();
  var bar = {
    name: 'bar',
    foo: foo
  };

  foo(); // window
  bar.foo(); // window

二. this绑定规则

1.绑定默认

  1. 当其他规则无法应用时将采用默人绑定
  2. 默认绑定将会绑定到全局对象
  3. 严格模式(strict mode)下不能讲全局对象用于默认绑定
function foo() {
    console.log(this === window);
  }
foo() // true

function bar() {
    "use strict";
    console.log(this === window);
    console.log(this);
  }
bar() // false undefined

2.隐式绑定

如果函数引用有上下文对象时,this将会绑定到这个对象。椎确来说是函数调用时是否有引用上下文对象。

  var name = 'window';
    function foo() {
      console.log(this.name);
    }
  var obj = {
    name: 'obj',
    foo: foo
  };
  obj.foo(); // obj 隐式绑定,上下文对象obj

  var bar = obj.foo;
  bar(); // window 无上下文对象

3.显示绑定

这也是常用的的方式:call、apply、bind 就不一一举例了。

  function foo() {
    console.log(this.name);
  }
  var obj = {
    name: 'obj'
  };
  foo.call(obj) // obj

4.new绑定

  var a;
  function foo(a) {
    this.a = a
  }
  var bar = new foo(2);

  console.log(a); //undefined
  console.log(bar.a); // 2  this了bar

三.优先级

  var a;

  function foo(a) {
    this.a = a;
  }

  var obj = {
    foo: foo
  };
  var obj2 = {};

  console.log(a); // undefined

  obj.foo(1);
  console.log(obj.a); // 1

  obj.foo.call(obj2, 2);
  console.log(obj2.a); // 2

  var baz = obj.foo.bind(obj2);
  var bar = new baz(3);
  console.log(bar.a); // 3

从上面的代码可以看出优先级从高到低依次是:new绑定、显示绑定、隐式绑定、默认绑定。