1.6 函数类 与 原型类 Functional Classes vs. Prototype Classes

发布于 2022-05-06 13:16:12 字数 4563 浏览 969 评论 0

函数类 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) 便达到了同样的效果

总结

  1. 查找变量,究竟是按照作用域链,还是原型链?没有继承时,只按照作用域链查;两者都有时,查不到是先查原型链,还是作用域?设计个实验?
  2. Obj.prototype.constructor 有什么用?
  3. https://blog.oyanglul.us/javascript/understand-prototype.html
  4. new Function() 有什么意义和区别?难道不是只有类才可以 new?
  5. http://www.ruanyifeng.com/blog/2011/06/designing_ideas_of_inheritance_mechanism_in_javascript.html
  6. http://www.liaoxuefeng.com/wiki/001434446689867b27157e896e74d51a89c25cc8b43bdb3000/0014344997013405abfb7f0e1904a04ba6898a384b1e925000
  7. 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

JSmiles

生命进入颠沛而奔忙的本质状态,并将以不断告别和相遇的陈旧方式继续下去。

文章
评论
84963 人气
更多

推荐作者

微信用户

文章 0 评论 0

小情绪

文章 0 评论 0

ゞ记忆︶ㄣ

文章 0 评论 0

笨死的猪

文章 0 评论 0

彭明超

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文