Javascript 学习笔记 12
ECMAScript 2015 发布了一个函数的扩展,可以使用模板字符串调用函数,与括号调用有所不同。
function solve(str, ...args) {
const { log } = console;
log(str);
log(args);
}
solve`Hello ${1}`; // 函数名后不空格,虽然会好看一点,但是不符合规范
/* 输出
[ 'Hello ', '' ]
[ 1 ]
*/
所以是啥意思呢?通俗的解释,就是普通字符串会被传到第一个参数,其他在 ${} 中的内容,则会依次传入后面的参数。
那么肯定会有人奇怪第一个输出的第二个元素是空字符串,如果我再写一段代码你就懂了:
function solve(str, ...args) {
const { log } = console;
log(str);
log(args);
}
solve`${0} Hello ${1}`; // 函数名后不空格,虽然会好看一点,但是不符合规范
/* 输出
[ '', ' Hello ', '' ]
[ 0, 1 ]
*/
也就是说它会以 ${xxx} 为分隔符分段,所以 ${xxx} 前后都是有内容的,即使是字符串的开头或结尾,与 String.prototype.split 行为一致。
所以标签函数是为了让参数更加语义化,既保证可读性,也保证实用性,我们可以利用此特性来实现一个 i18n 函数:
function i18n(str, name, age) {
return `我叫 ${name} ,今年 ${age} 岁了`;
// or String.raw({raw: str}, name, age);
}
i18n`My name is ${'Jack'},i am ${10} years old`;
// 我叫 Jack ,今年 10 岁了
可以看出,它还有类似词法分析器的功能,所以我们可以根据它来实现一门语言,我就写个例子来实现新的数组操作符:
function discriminate(operator) {
const [x, y] = operator.map(item => item.trim());
// x is a operator
if (x && !y) {
if (x == '++')
return 'unshift';
else if (x == '--')
return 'shift';
} else if (!x && y) {
if (y == '++')
return 'push';
else if (y == '--')
return 'pop';
} else {
return operator;
}
}
function convert(items) {
if (Array.isArray(items)) {
return items;
}
return [items];
}
function parser(operator, arr, items) {
items = convert(items);
operator = discriminate(operator);
switch (operator) {
case 'push':
arr.push(...items);
break;
case 'unshift':
arr.unshift(...items);
break;
case 'pop':
arr.pop();
break;
case 'shift':
arr.shift();
break;
case 'exec':
eval();
}
}
const arr = [1, 2];
parser` ${arr} ++ ${[3, 4]} `;
parser` -- ${arr} `;
parser` ${arr} -- `;
console.log(arr); // [ 2, 3 ]