JS -- 函数的三种角色

263 阅读1分钟
  1. 普通函数
    • 形参、实参、arguments、return、箭头函数
    • 私有作用域(栈内存、执行上下文)
    • 形参赋值 & 变量提升
    • 作用域链
    • 栈内存的释放和不释放(闭包)
    • ...
  2. 构造函数(类)
    • 类和实例
    • prototype 和 __proto__
    • instanceof
    • constructor
    • hanOwnProperty
    • ...
  3. 普通对象

注意点

  • 每一个函数(普通函数、类、内置类、Function)都是Function这个类的实例
Object.__proto__ === Function.prototype
Function.__proto__ === Function.prototype
  • 所有的对象都是Object这个类的实例
  • 函数也是对象(它有的属性:prototype、__proto__、length、name ...),所以所有的函数也是Object这个类的实例
function Foo() {
  getName = function () {
    console.log(1)
  }
  return this
}
Foo.getName = function () {
  console.log(2)
}
Foo.prototype.getName = function () {
  console.log(3)
}
var getName = function () {
  console.log(4)
}

function getName() {
  console.log(5)
}
Foo.getName() //2
getName() //4
Foo().getName() //1
getName() //1
new Foo.getName() //2  new (Foo.getName)()
new Foo().getName() //3  (new Foo()).getName()
new new Foo().getName() // 3  new ((new Foo()).getName)()
关于优先级  A = B > C
A: Foo.getName
B: new Fn()
C: new Fn
所以:
new Foo.getName(): 第一步优先执行let f = Foo.getName, 第二步 new f()  => new (Foo.getName)()。
new Foo().getName():优先级相等,从左向右执行 => (new Foo()).getName()。
new new Foo().getName() // 第一步先创建一个实例 let f = new Foo(), 变成new f.getName(), f.getName优先级大于 new f,所以先执行 let f2 = f.getName ,最后执行 new f2()  => new ((new Foo()).getName)()