1.6 函数类 与 原型类 Functional Classes vs. Prototype Classes
函数类 Functional Classes
这个起源自上一节 #135 我们发现的事情了:装饰模式可以用来创建对象或为对象添加属性。当其服务于第一种目的——创建对象——时,装饰模式便退化成了一个简单的函数类(用于创建对象的函数,设计模式里的 constructor 型模式)。这种情形也是我们上节所说,可以使用 ES6 提供的 class
语法糖来简化代码并达到相同效果的场景。
又说回 move
函数每次都要重新创建一个新实例的事情。我们还是想重构这个点,因此,退一步回来,有两个事情需要做:
- 将对象的方法还是移到全局下去
- 使用类似于
obj.extend(obj, methods)
的函数批量将所有方法在构造时添加到对象上去
let Car = function(location) { let car = { location: location } extends(car, Car.methods) // extends 并不是 JavaScript 原生的方法 return car } Car.methods = { move: function() { this.location++ }, on: function() { /* .. */ }, off: function() { /* .. */ } } let taxi = Car(3) let bus = Car(9) taxi.move() bus.move()
这样的解决方案其实是因为 JavaScript 没有原生类的支持而产生的方案。对比一下与静态语言的区别:
- 类:使用函数来模拟类的属性、方法等属性,并通过设定恰当的
this
值来支持此技术 - private 变量:没有类,也就没有类作用域,因此只能使用闭包,利用函数作用域来实现变量隐藏。但同时闭包作为一种函数级的方案更加灵活,在 Java 中,因为函数不能作为方法参数,要实现闭包同样的效果只能通过静态内部类来做到
原型类 Prototype Classes
使用函数类有两个问题:
- 每次方法都是手动拷贝到对象上去的,是在应用程序的层级上解决这个问题
- 每调用一次函数创建对象,都会生成一个新的完全相同的函数
于是我们就想,能不能不每个对象都拥有相同的属性或变量,类似于真正的面向对象的继承,我还是复用基类的,需要的时候向上查找就行了?当然可以。JavaScript 原生就提供了这个功能:prototype。
let Car = function(location) { let car = Object.create(Car.prototype) car.location = location return car } Car.prototype.move = function() { this.location++ } Car.prototype.on = function() { /* .. */ } // Car.prototype = { move: function() {}, on: function() {} } 会直接覆写 `Car.prototype`,是不推荐的实践 let taxi = Car(3) let bus = Car(9) taxi.move() bus.move()
主要的变化是:
method
改成了prototype
。其实prototype
就只是 JS 为此场景提供的一个更有标识度的关键词,可以认为与method
没什么区别,只是重命名了一下而已Object.create(Car.prototype)
创建出来的对象,便会把它找不到的属性和方法 delegate 到Car.prototype
(这里就是我们定义的方法)上查找,我们就省去了extends(obj, methods)
便达到了同样的效果
总结
- 查找变量,究竟是按照作用域链,还是原型链?没有继承时,只按照作用域链查;两者都有时,查不到是先查原型链,还是作用域?设计个实验?
- Obj.prototype.constructor 有什么用?
- https://blog.oyanglul.us/javascript/understand-prototype.html
new Function()
有什么意义和区别?难道不是只有类才可以 new?- http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
- http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014344997013405abfb7f0e1904a04ba6898a384b1e925000
- https://github.com/norfish/blog/wiki/%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3JavaScrip%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1%E5%92%8C%E5%8E%9F%E5%9E%8B%E7%BB%A7%E6%89%BF
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: React 栈(二):Redux
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论