Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

1.5 装饰模式 Object Decorator Pattern #135

Open
EthanLin-TWer opened this issue Mar 8, 2017 · 0 comments
Open

1.5 装饰模式 Object Decorator Pattern #135

EthanLin-TWer opened this issue Mar 8, 2017 · 0 comments
Assignees

Comments

@EthanLin-TWer
Copy link
Owner

EthanLin-TWer commented Mar 8, 2017

为什么突然讲这个呢?总结一下,这节讲的主要内容是:

  • 使用装饰模式来为对象添加属性,或用于创建对象
  • 尽可能使对象模块化(类化),可能是使用 this 关键字 的其中一种最佳实践

从课程讲的例子来看,装饰模式,顾名思义就是装饰对象。狭义来看,就是往对象上面添加属性,从而达到以一个函数来移除重复代码的目的。比如以下代码:

let amy = { location: 1 }
amy.location++

let ben = { location: 2 } 
ben.location++

其构造过程(即location属性的添加)可以通过装饰者模式来移除;而对 location 的操作可视为对象的行为,与面向对象的概念是很像的。上面的代码最终可以重构成下面这样,注意 this 关键字的应用:

let carlike = function(obj, location) { 
  obj.location = location
  obj.move = move
  return obj
}

let move = function() {
  return this.location++
}

let amy = carlike({}, 1)
let ben = carlike({}, 2)

amy.move()
ben.move()

进一步重构发现,move 函数其实只是用于操作 carlike 生产出来的对象,放到全局里面不合理。因此,我们尝试把它放到 carlike 函数里。不过要注意,这样的代价是,carlike 每被调用一次,就会生成一个函数(绑定到 move 上的函数),会占据更多的内存。

let carlike = function(obj, location) { 
  obj.location = location
  obj.move = function() {
    this.location++
  } 
  return obj
}

let amy = carlike({}, 1)
let ben = carlike({}, 2)

amy.move()
ben.move()

image

然而,我就发现,这个其实就是个很面向对象的简单类的构造:包括一个属性和方法。用 ES6 的 class 关键字即可轻松简明做到:

class Car {
  constructor(location) {
    this.location = location
  }

  move() {
    this.location++
  }
}

这解决了我以前很困惑的一个问题:ES6中的类只是函数的一个扩展。我一直没明白什么意思。现在看来,更清楚了,class说白了主要做了这样两件事:

  • 确保 this 绑定到正确的对象上,这样你可以正常地按照 obj.method() 的方式来调用而不需管 this 的问题。从概念模型上讲,它应该是发生在构造函数之前,因为构造函数里就可以使用 this 关键字了
  • 提供了定义对象方法的语法糖,背后做的事应该就是把你定义的函数绑定到对象上。因为对象实际上也只是一个函数,这也解释了为何类里即使引用同一个类的方法,也需要加 this.anotherMethod() 关键字
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant