JavaScript 函数 Currying 化

JavaScript 和我了解的其他编程语言,例如 C/C++、C#、Java,有一个很独特的语法特性,函数也是一种对象。既然作为对象,那么也有属性、方法。今天恰好有一个问题引入,对于 argumentsapply()call() 以及 Currying 有了初步的了解,简单做个记录。

arguments 对象

这是一种类似于 Array 的对象,可以在每个函数内部调用。例如:

function foo(a, b, c) {
    console.log(arguments[0]);
    console.log(arguments.length);
}

foo(1, 2, 3); // expected output 1

arguments 对象并不是 Array,没有继承 Array 的方法,比如 slice()pop()。但是可以使用 call 的方式使用 Array 的函数,例如以下几种方式:

var args1 = Array.prototype.slice.call(arguments);

// 使用子面值,书写更短但是会创建空的数组对象
var args2 = [].slice.call(arguments);

// ES2015
var args3 = Array.from(arguments);

// spread syntax
var args4 = [...arguments];

好了,挖了一个新坑 Array.from() 以及 spread syntax operator,以后再整理。

除了 length 这个属性外,还有其他几个属性,这里暂不展开讨论:

  • arguments.callee 当前 arguments 对象所属的函数
  • arguments.caller 调用当前函数的函数,这个属性已经不一定可用了
  • arguments[@@iterator] ES2015 (6th Edition, ECMA-262) 中所引入的迭代器访问方式。

回调函数小对比

JavaScript 中函数是 Function 对象,因此可以很方便的将函数作为参数传递给另一个函数,这大大方便了异步编程。最简单的例子:

function foo(callback) {
	if (typeof callback === "function") {
		callback("hi there");
	}
}

foo(function(param) {
	console.log(param);
});

addEventListener()fetch 都会大量用到回调函数。回调函数的另一个好处在于代码复用更加的灵活,所以回调函数在很多语言中都有方式。恰好最近在重构一段 Java 代码,索性将我了解的几种语言做一次小结。

C

在 C 语言中回调函数是以函数指针(function pointer)的形式体现的。示例代码中 fun_ptr 指向了函数 foo 的地址,自然可以把 fun_ptr 当作变量传递给另一个函数。

#include <stdio.h>

void foo(int i) {
	printf("the value of input is %d\n", i);
}

int main() {
	void (*fun_ptr)(int) = foo;

	(*fun_ptr)(42);

	return 0;
}

近期工作中学到的一些 SQL 技巧

SQL 一直是我的弱项,在以往的开发中和 SQL 打交道实在有限。借着近期项目,尝试将尽量多的操作放在 SQL 中(而非返回到编程语言中)确实很好玩。以下是以 MySQL 为例。

新增数据后返回主键 ID

一种方法是使用数据库内置的 LAST_INSERT_ID() 函数:

insert into foo() values();
select LAST_INSERT_ID();

另一种办法是在 Java 里,创建 PreparedStatement 的时候就指定好(通过 Connection.prepareStatement(String, int) API),执行后再调用 Statement.getGeneratedKeys() API

PreparedStatement p = conn.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS);
p.executeUpdate();
ResultSet r = p.getGeneratedKeys();

初次接触 WebAssembly 以及一些 tricks

这周从事一些需求分析工作,因此有机会接触到一些尚未了解的技术,看看是否能解决需求。

WebAssembly

有关 wasm 的资料现在很多了,简而言之就是将代码编译为特定的二进制代码,供浏览器去执行,MDN 上介绍了详细的概念, 包括目标以及三种编写方式。Wasm 并不是传统意义上的汇编语言,它只是充分利用了 JavaScript VM,类似于 .Net 或者 Java 编译后的中间代码。报道说,eBay 使用 WebAssembly 给 WebApp 提升了 50 倍的性能。这里有更多 use cases 可供参考,以及 FAQ

一道算法和一些(我认为有趣的)开源项目

这周的内容有点水,简单分享下这周学到的东西。

算法

LC 342 - Power of 4 without loop/recursion

这个题目有点意思。抛开 1(0x0000 0001) 这个例外,像 4(0x0000 0100)16(0x0001 0000)64(0x0100 0000) 可以观察到二进制形式下很有规律,只有一位是 1,接下来跟着偶数个 0 (否则就是 2 的幂)。代码参考自 https://www.geeksforgeeks.org/find-whether-a-given-number-is-a-power-of-4-or-not/

a) There is only one bit set in the binary representation of n (or n is a power of 2)

b) The bits don’t AND(&) any part of the pattern 0xAAAAAAAA

/**
 * @param {number} num
 * @return {boolean}
 */
var isPowerOfFour = function(num) {
    return (num != 0) && ((num&(num-1)) == 0) && !(num & 0xAAAAAAAA);
};