JavaScript getter-setter金字塔
JamesZhang80078 人气:0引言
英文链接: staltz.com/javascript-…
函数是JavaScript的基石。 它是一种灵活的、抽象的,可作为其他抽象的基础, 如:Promise、Iterables、Observables等。 之前我在会议或研讨会中传递这些概念,随着时间的推移,我发现这些抽象的概念可以抽象为金字塔状排列的模型,在本文中,将介绍金字搭中的各层。
函数
JavaScript的基础是一级值,如: numbers、strings、objects、booleans等。 虽然,您可以只使用这些值和控制流(if/else/for等)来编写程序,但很快您可能需要编写一个新的函数来改进您的程序。
JavaScript中必须通过函数进行抽象,像异步I/O操作等通常都必须使用callback回调函数。 JavaScript中的函数,与【函数式编程】中的纯函数
不同,建议最好将它们简单理解为“流程”,因为它只得惰性的可重用代码块,具有可选的输入(参数)和可选的输出(返回值)
与硬编码相比,函数有以下几个重要的好处:
- 懒惰/可重用性, 函数内的代码必须是惰性的(即除非被调用,否则不会执行)才能使其可重用
- 实现的灵活性,函数的使用者并不关心函数内部是如何实现的,这意味着可以各种方式灵活的实现函数。
getters
getter是一种不用传递任何参数但需要有返回值的函数。
函数定义: () => X
getter是一种不用传递任何参数但需要有返回值的函数。 JavaScript中有许多这样的getter, 例如: Math.random()、Date.now()等
getter作为值的抽象也很有用,例如:user
与 getUser
:
const user = {name: 'Alice', age:30}; console.log(user.name); // Alice function getUser(){ return {name: 'Alice', age:30}; } console.log(getUser().name); // Alice
通过使用getter, 我们可以利用函数的一个好处: 惰性
. 即我们不调用 getUser()
,user
对象就不会被白白创建。 同时,我们利用了函数的另一好处:实现的灵活性, 因为我们可以通过多种不同的方式来返回对象。
getter还允许我们对副作用有一个钩子,当执行getter时,我们可以触发有用的副作用函数,比如console.log
输出日志 或是 触发Analytics事件等,例如:
function getUser(){ Analytics.sendEvent('User object is now being accessed'); return {name:'Alice', age:30}; }
getter上的计算,也是可以抽象的。例如:
function add(getX, getY){ return function getZ(){ const x = getX(); const y = getY(); return x + y; } }
当getter返回不可预测的值时,这种抽象计算的好处更加明显,例如:使用getter添加Math.random
:
const getTen = () => 10; const getTenPlusRandom = add(getTen, Math.random); console.log(getTenPlusRandom()); // 10.948117215055046 console.log(getTenPlusRandom()); // 10.796721274448556 console.log(getTenPlusRandom()); // 10.15350303918338 console.log(getTenPlusRandom()); // 10.829703269933633
比较常见的是getter与Promise一起搭配使用,因为Promise是不可重用的计算,因此,将Promise的构造函数包装在一个getter中(如我们熟知的"工厂函数"或"thunk")使其可重用。
setters
setters是有一个或多个输入参数,但没有返回值的函数。
函数定义: X => ()
setters是有一个或多个输入参数,但没有返回值的函数。 在JavaScript运行时或DOM中有许多这样的setters, 比如: console.log(x), document.write(x)
等。
与getter不同,setter通常不用抽象。 因为函数没有返回值,这意味着函数仅用于发送数据或执行JavaScript命令等。 例如, 上文中的getter getTen
是数字10的抽象,我们可以将它作为值进行传递,但如果将函数setTen
作为值传递是没有意义的,因为它没有返回值。
换句话说,setter可以是其他setter的简单包装器。例如:简单包装下setter console.log
:
function fancyConsoleLog(str) { console.log('⭐ ' + str + ' ⭐'); }
getter-getters
getter-getters是一种不需要输入参数且返回一个getter的函数。
函数定义: () => (() => X)
“getter-getter”: 一种特殊类型的getter,其返回值是一个getter.
对getter的原始需求是使用getter
的返回值进行迭代。
例如,我们想显示二次幂的数字序列,我们可以使用getter getNextPowerOfTwo()
let i = 2; function getNextPowerOfTwo() { const next = i; i = i * 2; return next; } console.log(getNextPowerOfTwo()); // 2 console.log(getNextPowerOfTwo()); // 4 console.log(getNextPowerOfTwo()); // 8 console.log(getNextPowerOfTwo()); // 16 console.log(getNextPowerOfTwo()); // 32 console.log(getNextPowerOfTwo()); // 64 console.log(getNextPowerOfTwo()); // 128
在上面示例代码中,变量i
是全局声明的,若我们想重新迭代序列,则必须要重置变量i
, 从而泄漏了getter的实现细节。
若想将上述代码变为可重用且不包含全局变量,我们需要将getter封装在另一个函数中,这个包装函数也是一个getter.
function getGetNext() { let i = 2; return function getNext() { const next = i; i = i * 2; return next; } } let getNext = getGetNext(); console.log(getNext()); // 2 console.log(getNext()); // 4 console.log(getNext()); // 8 getNext = getGetNext(); //
加载全部内容
- 猜你喜欢
- 用户评论