亲宝软件园·资讯

展开

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(); // 

加载全部内容

相关教程
猜你喜欢
用户评论