理解原型链
在 JavaScript 的世界中, 函数是一等公民.
上面这句话在很多地方都看到过. 用我自己的话来理解就是: 函数既当爹又当妈."当爹" 是因为我们用函数去处理各种 "粗活累活"(各种工具函数, 页面交互, 业务逻辑等);"当妈" 是因为函数还会 "生孩子"(创建对象).
在 JavaScript 的世界中, 每一个对象都有一个隐藏的 proto 属性. 这个属性指向生成这个对象的构造函数的原型(prototype). 事实上, 所有函数都有一个原型. 考虑如下例子:
- function Human() {}
- var h1 = new Human()
- var h2 = new Human()
- // h1 和 h2 都是是由 Human 函数创建出来的对象(称为 Human 的实例对象), 所以:
- h1.__proto__ = Human.prototype
- h2.__proto__ = Human.prototype
- // Human.prototype 是一个对象(且称为原型对象吧), 因此可以给它添加一些属性或者方法, 比如:
- Human.prototype.legs = 2
- Human.prototype.sleep = function() {
- console.log('sleeping....')
- }
所有实例对象都可以访问到相应原型对象里面的属性和方法.(理解原型链的关键)
- // 不难得出结论:
- h1.legs === 2 // true
- h2.legs === 2 // true
- h1.sleep() // sleeping....
- h2.sleep() // sleeping....
实现继承
再看另外一个构造函数:
- function Coder() {
- }
- // 如果在这里把 Human 的原型赋给 Coder 的原型
- Coder.prototype = Human.prototype
- // 接着再添加一些 Coder 自己的原型方法和属性
- Coder.prototype.age = 24
- Coder.prototype.work = function() {
- console.log('write code')
- }
- // 新建一个 Coder 对象
- var c1 = new Coder()
- // 不难得出
- c1.age === Coder.prototype.age // true 24
- c1.work === Code.prototype.work // true
- c1.legs === Human.prototype.legs // true 2
- c1.sleep === Human.prototype.sleep // true
- http://jsfiddle.net/kkkisme/asp3auyo/3/
- Coder.prototype.sleep = function() {
- console.log('still write code....')
- }
- // 修改了 Coder 的原型, 但同时也会影响 Human 的原型
- // 因此需要修改 Coder.prototype 的指向从而避免这个问题
- Coder.prototype = h1 // h1 是 Human 的一个实例
- Coder.prototype = new Human()
- // 或者
- Coder.prototype = Object.create(Human.prototype)
- // 实际上这两种写法还是有一定的区别
- function Coder(arg) {
- Human.call(this, arg)
- // 接着再写自身的属性(方法)
- }
来源: http://www.qdfuns.com/article/51117/0a46950fc3b5813480f624a2c9a3988b.html