JS输出


考察函数和作用域的 PRIORITY,以及 new 在执行时的一些机制。需要结合执行上下文来分析函数和变量声明的顺序与优先级。

题目

function Foo() {
  getName = function () {
    console.log("11=>", 11)
  }
  return this
}
Foo.getName = function () {
  console.log("22=>", 22)
}
Foo.prototype.getName = function () {
  console.log("33=>", 33)
}
var getName = function () {
  console.log("44=>", 44)
}
function getName() {
  console.log("55=>", 55)
}

Foo.getName()
getName()
Foo().getName()
getName()
new Foo.getName()
new Foo().getName()
new new Foo().getName()

// 22=> 22
// 44=> 44
// 11=> 11
// 11=> 11
// 22=> 22
// 33=> 33
// 33=> 33

分析

  1. Foo.getName() 调用的是 Foo 上的静态方法,输出 22。
  2. 第一次调用 getName() 输出 44,调用的是全局作用域下声明的 getName 变量函数。
  3. Foo().getName() 输出 11,Foo() 构造函数内部声明的 getName 变量,优先级最高。
  4. 第二次调用 getName() 输出 11,因为被 Foo() 内的 getName 覆盖了。
  5. new Foo.getName() 输出 22,new 执行的是 Foo 上的静态方法。
  6. new Foo().getName() 输出 33,new Foo() 创建了一个实例,调用的是原型上的方法。
  7. new new Foo().getName() 也输出 33,新的语法并没有改变其机制,仍然执行原型上的方法。

收获

  1. 远算优先级
  • 分组(…)19
  • 成员访问(a.b) ,new(带参数了;列表),函数调用,可选链 优先级较高 为 18
  • new(无参数列表) 17 new Foo 属于无参数列表
  • 后置递增 /递减 16
  • 赋值 (从右到左) 2
  1. new 关键字会进行如下的操作:
  • 创建一个空的简单 JavaScript 对象(即 {});
  • 为步骤 1 新创建的对象添加属性 proto,将该属性链接至构造函数的原型对象;
  • 将步骤 1 新创建的对象作为 this 的上下文;
  • 如果该函数没有返回对象,则返回 this。
  1. .new的优先级
  • . 当 new 和 . 同时出现时,new 的优先级更高,例如:
    new Foo().getName()
    这里 new Foo()会先执行。
  • 当 . 在 new 的参数位置时,. 的优先级更高,例如:
    new Foo.getName()
    这里 Foo.getName 会先解析。
  • 当 . 不在 new 的参数位置时,new 的优先级更高。

这么设定优先级主要基于以下考虑:

  • new 作为创建实例的运算符,应该先执行。
  • . 在 new 的参数位置时,要先解析出一个静态方法。
  • . 不在参数位置时,应该作用于 new 创建的实例上。

文章作者: 高红翔
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 高红翔 !
  目录