js的this指向

126 阅读2分钟

作为日常开发中通常只用class继承, 变量只用let/const, 绑定时明确绑定从不搞隐式绑定的人, 感觉this指向这样的题目真是反人类..

这年头老喜欢搞一些屠龙技的题目

变量声明与隐式绑定

  1. var: 当使用var 作为声明方法时, 如果是在块级作用域中, 则此时隐式作用范围为在函数内(与let/const差不多), 如果不在块级作用域中, 则此时隐式绑定到全局上下文中. (在块级作用域时即便当前this指向了全局上下文, 也不会隐式绑定到全局上下文中)
  2. let/const 不管是否在块级作用域中, 都不会隐式绑定到全局上下文上.
  3. function: 作用与var一致, 但有一点要注意的是, 如果function前后存在var定义的同名函数, 则此时以var定义的函数优先级最高(同时执行时!!), 如果是分两次输入执行时, 此时后输入的内容会覆盖前面的内容!!!(奇葩)

全局上下文

非严格模式和严格模式中this都是指向顶层对象(浏览器中是window)。

this === window // true
'use strict'
this === window;
this.name = 'name1';
console.log(this.name); // name1

函数上下文

  1. 不使用new时, 默认的函数上下文为全局上下文
  2. 使用new操作符调用函数,会自动执行以下步骤。
  1. 创建了一个全新的对象。
  2. 这个对象会被执行[[Prototype]](也就是__proto__)链接。
  3. 生成的新对象会绑定到函数调用的this
  4. 通过new创建的每个对象将最终被[[Prototype]]链接到这个函数的prototype对象上。
  5. 如果函数没有返回对象类型Object(包含FunctoinArrayDateRegExgError),那么new表达式中的函数调用会自动返回这个新的对象。

每个函数都可以认为是一个单独的对象, 直接在对象中添加变量不会在new 后继承, 只有在prototype上添加变量才能在new 后继承

以下是测试题:

function test() {
  function getName() {
    console.log(1)
  }
  return this
}

test.getName = function() {
  console.log(2);
}

test.prototype.getName = function () {
  console.log(3);
}

var getName = function () {
  console.log(4);
}

function getName () {
  console.log(5);
}
getName()
test.getName();
test().getName();
getName()
new test.getName()
new test().getName()
new new test().getName();