new
首先来讲 new , 这个关键词主要就是用在创建类或函数的实例上的。当然, 类其实是构造函数的语法糖, 让语言的表达更直观。
new 的操作流程如下:
- 创建空的 JavaScript 对象, Object.create(null)
- 指定构造函数, 绑定原型链, obj.__proto__ = Func.prototype
- 绑定obj为this后运行 Func.call(obj,arguments) 获得返回值
- 判断返回值是否为对象, 否定的话返回构造的对象, 肯定的话返回既定返回值
1 | function test(name){ |
可以看到即使 test 函数没有使用 return 仍然返回了一个对象。如果更改一下test函数的话:
1 | function test(name){ |
此时, 失去了构造函数 test。
1 | function test(name){ |
也就是说如果返回值为 Object 类型的话,就直接返回该 Object,否则返回新创建的空对象。
然后来说一下原型链。
prototype
所有的对象都有隐藏属性 __proto__
这个属性指向构造这个对象的构造函数的原型对象 prototype
, 因此对象能够使用构造函数上所定义的方法和属性。
函数除了有着作为对象拥有的 __proto__ 还有着 prototype 属性, 这个属性指向了包含所有实例共享的属性和方法的对象。原型对象也有一个属性,叫做constructor,这个属性包含了一个指针,指回原构造函数。这就是为什么常见改了prototype后将constructor改回来的原因
在这里提一下规范所定义的函数:
对象类型的成员,标准内置构造器 Function的一个实例,并且可做为子程序被调用。
PS: 如果在chrome 控制台那想看看函数的内部属性, 用console.dir()
1 | function test(){} |
Object本身是构造函数,继承了Function.prototype; Function也是对象,继承了Object.prototype。Object -> Function -> Array/String/Date
Object.prototype是对象,但它不是通过Object函数创建的。Object.prototype谁创建的,它是v8引擎(假设用的都是chrome浏览器)–引自参考文章
纯理论难搞, 不要理他最好
1 | Object instanceof Function // true |
由 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 | $.prototype.test = 1; |
使用 prototype 继承的方法
太多了, 由于我现在完全没有用过这些(设计模式), 在这里也只能给文章或红宝书(JavaScript高级程序设计)去看看吧
1 | function a(){} |
判断继承的方法
instanceof 关键字, 凡是原型链上出现过的构造函数都算
1
2
3
4
5function a(){}
function b(){}
b.prototype = new a()
var c = new b()
c instanceof a/b/Object //true/true/trueisPrototypeOf()
参考文章: