this指向要点及练习题

88 阅读3分钟

要点

  • 函数内部直接调用的函数 this 指向 window
  • 箭头函数的 this 指向是在声明时就确定了的,不会被更改
  • new 出来的函数的 this 指向是实例对象
  • bind 和箭头函数优先级较高

练习题

1

var obj = {
  a: 10,
  b: this.a + 10,
  fn: function () {
    return this.a;
  },
};

console.log(obj.b);
console.log(obj.fn());
  • 答案
// NaN 对象里面没有this指向,对象里面的this指向和它所在的作用域保持一致。指向window
// 10 obj. 时指向obj  指向obj

2

var a = 20;
var obj = {
  a: 10,
  getA: function () {
    return this.a;
  },
};

console.log(obj.getA());
var test = obj.getA;
console.log(test());
  • 答案
// 10 obj. 指向obj
// 20 在window中调用,指向window

3

var a = 5;

function fn1() {
  var a = 6;
  console.log(a);
  console.log(this.a);
}

function fn2(fn) {
  var a = 7;
  fn();
}

var obj = {
  a: 8,
  getA: fn1,
};
fn2(obj.getA);
  • 答案
// 6 跟指向无关,作用域问题
// 5 指向window

4

function fn() {
  var a = 1;
  var obj = {
    a: 10,
    c: this.a + 20,
  };
  return obj.c;
}
console.log(fn());
  • 答案
// NaN 指向window

5

function Person(name, age) {
  this.name = name;
  this.age = age;
  console.log(this);
}
Person.prototype.getName = function () {
  console.log(this);
};
var p1 = new Person('test', 18);
p1.getName();
var p2 = p1.getName;
p2();
  • 答案
// Person {name: 'test', age: 18} 指向Person实例对象
// Person {name: 'test', age: 18} 指向Person实例对象
// window 指向window

6

var obj = {
  foo: 'test',
  fn: function () {
    var mine = this;
    console.log(this.foo);
    console.log(mine.foo);
    var fun = function () {
      console.log(this.foo);
    };
    fun();
    (function () {
      console.log(this.foo);
      console.log(mine.foo);
    })();
  },
};
obj.fn();
  • 答案
// test obj. 指向obj
// test obj. 指向obj
// undefined 方法的内部函数的this指向window
// undefined 方法的内部函数的this指向window
// test obj. 外部存this 指向obj

7

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

var a = 2;
var o = {
  a: 3,
  foo: foo,
};
var p = {
  a: 4,
};
o.foo();
(p.foo = o.foo)();

p.foo = o.foo;
p.foo();
  • 答案
// 3 obj. 指向对象o
// 2 赋值后返回的是赋上的值 指向window
// 4 obj. 指向对象p

8

function foo() {
  console.log(this.a);
}
var obj1 = {
  a: 3,
  foo: foo,
};
var obj2 = {
  a: 5,
  foo: foo,
};
obj1.foo();
obj2.foo();
obj1.foo.call(obj2);
obj2.foo.call(obj1);
  • 答案
// 3 obj. 指向对象obj1
// 5 obj. 指向对象obj2
// 5 call 被修改this指向到obj2
// 3 call 被修改this指向到obj1

9

function test(arg) {
  this.x = arg;
  console.log(this);
  return this;
}
var x = test(5);
var y = test(6);

console.log(window.x.x);
console.log(y.x);
  • 答案
// window
// window
// undefined
// 6
  • 解析

    • 首先执行了var x = test(5);,这个过程中先将 window 中的 x 置为了 5,然后将 window 中的 x 置为了 window 对象;此时 window.x = window
    • 然后执行了var y = test(6);,这个过程将 window.x 设置成了 6,然后将 y 设置成了 window;此时window.x = 6,y = window
    • 所以windwo.x.x也就是6.x为 undefined,y.x也就是window.x为 6

10

var obj = {
  data: [1, 2, 3, 4, 5],
  data2: [1, 2, 3, 4, 5],
  fn: function () {
    console.log('-----test-----');
    console.log(this);
    return this.data.map(function (item) {
      console.log(this);
      return item * 2;
    });
  },
  fn2: function () {
    console.log('-----test2-----');
    console.log(this);

    return this.data2.map((item) => {
      console.log(this);
      return item * 2;
    });
  },
};
obj.fn();
obj.fn2();
  • 答案
// obj obj. 指向obj
// window * 5 函数内调用函数指向window
// obj obj. 指向obj
// obj * 5 箭头函数 指向外部this

11

function func(num) {
  this.count++;
}

func.count = 0;
func(1);
console.log(func.count);
  • 答案
// 0 func被调用时指向window和func.count没有关系

12

obj = {
  func() {
    const arrowFunc = () => {
      console.log(this._name);
    };

    return arrowFunc;
  },

  _name: 'obj',
};

obj.func()();

func = obj.func;
func()();

obj.func.bind({ _name: 'newObj' })()();

obj.func.bind()()();

obj.func.bind({ _name: 'bindObj' }).apply({ _name: 'applyObj' })();
  • 答案
// func中return函数为箭头函数,this指向其外部函数的this指向
// 'obj' 指向obj
// undefined 指向window
// 'newObj' 指向bind中的函数
// undefined 指向window
// 'bindObj' bind函数的this指向不会被改变 指向bind中的对象

13

function a() {
  var a = 12;
  var obj = {
    a: 1,
    b: this.a + 10,
  };
  console.log(obj.b);
  console.log(this.a);
}
a();
  • 答案
// fun a 10 this指向window
// fun a this指向window