prototype new

new

首先来讲 new , 这个关键词主要就是用在创建类或函数的实例上的。当然, 类其实是构造函数的语法糖, 让语言的表达更直观。

new 的操作流程如下:

  1. 创建空的 JavaScript 对象, Object.create(null)
  2. 指定构造函数, 绑定原型链, obj.__proto__ = Func.prototype
  3. 绑定obj为this后运行 Func.call(obj,arguments) 获得返回值
  4. 判断返回值是否为对象, 否定的话返回构造的对象, 肯定的话返回既定返回值

具体可以看

1
2
3
4
function test(name){
this.name = name
}
var a = new test(123) //test {name: 123}

可以看到即使 test 函数没有使用 return 仍然返回了一个对象。如果更改一下test函数的话:

1
2
3
4
5
6
7
function test(name){
this.name = name
return {
age:18
}
}
var a = new test(123) // {age: 18}

此时, 失去了构造函数 test。

不同返回情况下所得对象

1
2
3
4
5
function test(name){
this.name = name
return 123
}
var a = new test(123) // test {name: 123}

不同返回情况下所得对象

也就是说如果返回值为 Object 类型的话,就直接返回该 Object,否则返回新创建的空对象。

然后来说一下原型链。

prototype

所有的对象都有隐藏属性 __proto__ 这个属性指向构造这个对象的构造函数的原型对象 prototype , 因此对象能够使用构造函数上所定义的方法和属性。

函数除了有着作为对象拥有的 __proto__ 还有着 prototype 属性, 这个属性指向了包含所有实例共享的属性和方法的对象。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。这就是为什么常见改了prototype后将constructor改回来的原因

在这里提一下规范所定义的函数:

对象类型的成员,标准内置构造器 Function的一个实例,并且可做为子程序被调用。
PS: 如果在chrome 控制台那想看看函数的内部属性, 用console.dir()

1
2
3
4
5
6
7
function test(){}
test.__proto__ === Function.prototype // true
test.apply // ƒ apply() { [native code] }

Function.__proto__ === Object.prototype // false
Function.prototype.__proto__ === Object.prototype // true
Function.prototype === Function.__proto__ // true

Object本身是构造函数,继承了Function.prototype; Function也是对象,继承了Object.prototype。
Object -> Function -> Array/String/Date

Object.prototype是对象,但它不是通过Object函数创建的。Object.prototype谁创建的,它是v8引擎(假设用的都是chrome浏览器)–引自参考文章
纯理论难搞, 不要理他最好

1
2
Object instanceof Function // true
Function instanceof Object // true

 如果不为null的话在沿着原型链查找时会无限循环

由 prototype 而来的继承

许多OO(面向对象)语言都支持两种继承方式: 接口继承 和 实现继承。接口继承只继承方法签名, 而实现继承则继承实际的方法。由于js中方法没有签名,在ECMAScript规范中无法实现接口继承。因此js没有重载, 所有参数放在 arguments

1
test(char* a, double b);//只有有强类型的语言才会有函数签名, 函数名+参数类型组合出签名

当试图从某个对象上使用属性或方法时:
1.首先 obj 内部属性
2.obj.__proto__ 也就是构造函数(constructor)的prototype上找
3.还是没有的话constructor.prototype.__proto__上找直到null (构造函数本身也是对象)

constructor 自身是没法使用自己的原型链上的函数的

1
2
$.prototype.test = 1;
console.log($.test) //undefined

使用 prototype 继承的方法

太多了, 由于我现在完全没有用过这些(设计模式), 在这里也只能给文章或红宝书(JavaScript高级程序设计)去看看吧

1
2
3
function a(){}
function b(){}
b.prototype = new a()//b.prototype.__Proto__ === a.prototype

判断继承的方法

  1. instanceof 关键字, 凡是原型链上出现过的构造函数都算

    1
    2
    3
    4
    5
    function a(){}
    function b(){}
    b.prototype = new a()
    var c = new b()
    c instanceof a/b/Object //true/true/true
  2. isPrototypeOf()


参考文章:

JavaScript深入之new的模拟实现

JS原型链与继承别再被问倒了

js中proto和prototype的区别和关系?

从探究Function.__proto__===Function.prototype过程中的一些收获

文章作者:
文章链接: https://luckyray-fan.github.io/2019/09/29/prototype-new/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 luckyray