字符串的扩展和函数的扩展

91 阅读7分钟

字符串的扩展

字符串的遍历接口器

在 JavaScript 中,字符串是一个可迭代对象,这意味着你可以使用 for...of 循环或其他迭代器接口来遍历字符串中的每一个字符。

for...of 遍历字符串

const str = "Hello";
​
for (const char of str) {
    console.log(char);
}
// 输出:
// H
// e
// l
// l
// o

使用迭代器遍历字符串

你可以手动获取字符串的迭代器并遍历它:

const str = "Hello";
const iterator = str[Symbol.iterator]();
​
let result = iterator.next();
while (!result.done) {
    console.log(result.value);
    result = iterator.next();
}
// 输出:
// H
// e
// l
// l
// o

模板字符串

模板字符串(Template Strings)是 ES6 引入的一种用于处理字符串的增强语法。它使用反引号 ``( ` ``)包围,可以在字符串中嵌入变量、表达式或多行文本。

基本用法

const name = "Alice";
const greeting = `Hello, ${name}!`;
console.log(greeting); // 输出 'Hello, Alice!'

多行字符串

const text = `This is
a multi-line
string.`;
console.log(text);
// 输出:
// This is
// a multi-line
// string.

表达式插值

在模板字符串中,可以直接插入表达式:

const a = 5;
const b = 10;
console.log(`The sum of ${a} and ${b} is ${a + b}.`);
// 输出 'The sum of 5 and 10 is 15.'

字符串新增方法

传统上,JavaScript 只有indexOf方法,可以用来确定一个字符串是否包含在另一个字符串中。ES6 又提供了三种新方法。

  • includes() :返回布尔值,表示是否找到了参数字符串。
  • startsWith() :返回布尔值,表示参数字符串是否在原字符串的头部。
  • endsWith() :返回布尔值,表示参数字符串是否在原字符串的尾部。
let s = 'Hello world!';
​
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

这三个方法都支持第二个参数,表示开始搜索的位置。

let s = 'Hello world!';
​
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

上面代码表示,使用第二个参数n时,endsWith的行为与其他两个方法有所不同。它针对前n个字符,而其他两个方法针对从第n个位置直到字符串结束。

函数扩展

Rest 参数总结

Rest 参数(Rest Parameters)是 ES6 引入的一种语法,用于表示函数的可变参数。它允许你将不确定数量的参数打包成一个数组,方便在函数内部进行处理。

基本语法

Rest 参数使用三个点 ... 作为前缀,后跟一个参数名,该参数名会成为一个数组,包含所有传递给函数的额外参数。

function sum(...numbers) {
    return numbers.reduce((total, num) => total + num, 0);
}
​
console.log(sum(1, 2, 3)); // 输出 6
console.log(sum(10, 20));  // 输出 30

在这个例子中,numbers 是一个数组,包含了所有传入的参数,函数通过数组的 reduce 方法将它们相加。

规则和特性

  1. Rest 参数必须是最后一个参数

    • Rest 参数只能作为函数的最后一个参数,因为它会捕获所有剩余的参数。
    function greet(greeting, ...names) {
        return `${greeting} ${names.join(', ')}`;
    }
    ​
    console.log(greet('Hello', 'Alice', 'Bob', 'Charlie')); // 输出 'Hello Alice, Bob, Charlie'
    
  2. Rest 参数可以与其他参数一起使用

    • 你可以在函数中定义固定的参数,然后使用 Rest 参数来捕获剩余的参数。
    function multiply(multiplier, ...numbers) {
        return numbers.map(num => num * multiplier);
    }
    ​
    console.log(multiply(2, 1, 2, 3)); // 输出 [2, 4, 6]
    
  3. Rest 参数与 arguments 对象的区别

    • Rest 参数与 arguments 对象不同,arguments 是一个类似数组的对象,包含所有传递给函数的参数,而 Rest 参数是一个真正的数组。
    • arguments 对象包含所有参数,而 Rest 参数只包含那些未被命名的额外参数。
    function showArgs(...args) {
        console.log(args); // 使用 Rest 参数,输出一个数组
    }
    ​
    function showArguments() {
        console.log(arguments); // 使用 arguments 对象,输出类似数组的对象
    }
    ​
    showArgs(1, 2, 3); // 输出 [1, 2, 3]
    showArguments(1, 2, 3); // 输出 { '0': 1, '1': 2, '2': 3 }
    
  4. Rest 参数不能与普通参数混用

    • Rest 参数必须放在参数列表的最后,不能在 Rest 参数后面再添加其他参数。
    // 错误示范
    function test(...args, lastArg) {
        // 语法错误
    }
    

常见使用场景

  1. 可变参数的函数

    • Rest 参数非常适合用于那些参数数量不定的函数,例如求和函数、拼接字符串函数等。
    function concatenate(...strings) {
        return strings.join('');
    }
    ​
    console.log(concatenate('Hello', ' ', 'World', '!')); // 输出 'Hello World!'
    
  2. 数组操作

    • Rest 参数可以用来轻松地将函数参数转换为数组,从而使用数组方法进行处理。
    function sortNumbers(...numbers) {
        return numbers.sort((a, b) => a - b);
    }
    ​
    console.log(sortNumbers(5, 3, 8, 1)); // 输出 [1, 3, 5, 8]
    
  3. 替代 arguments 对象

    • 使用 Rest 参数替代 arguments 对象,可以获得更干净、更明确的代码,因为 Rest 参数是一个真正的数组,支持所有数组方法。
    function oldFunction() {
        const args = Array.prototype.slice.call(arguments);
        // 旧方法使用 arguments 对象
    }
    ​
    function newFunction(...args) {
        // 新方法直接使用 Rest 参数
    }
    

注意事项

  • 兼容性:Rest 参数是 ES6 引入的,在老旧的 JavaScript 环境中可能不受支持。如果需要支持旧环境,可能需要使用 Babel 等工具进行编译。
  • 性能:虽然 Rest 参数提供了便利,但在性能关键的代码中应小心使用,因为将参数打包成数组可能引入不必要的开销。

总结

  • Rest 参数 是一种灵活的函数参数处理方式,允许捕获任意数量的参数并打包成数组。
  • 语法简洁:使用 Rest 参数可以替代 arguments 对象,并且由于它是一个真实的数组,因此更加易用和直观。
  • 应用场景广泛:Rest 参数适用于可变参数的函数、数组操作、以及需要替代 arguments 的场景。
  • 限制:Rest 参数必须是最后一个参数,且不能与其他普通参数混用。

Rest 参数为函数参数处理带来了极大的灵活性,使得编写可变参数函数更加简洁和易于理解。

箭头函数

箭头函数(Arrow Functions)是 ES6 引入的一种更简洁的函数表达式写法,它提供了更简洁的语法,并且在处理 this 关键字时具有不同的行为。

基本语法

箭头函数的语法比传统函数表达式更简洁:

// 传统函数表达式
const add = function(a, b) {
    return a + b;
};
​
// 箭头函数
const add = (a, b) => a + b;

语法规则

  1. 无参数

    const greet = () => 'Hello, world!';
    
  2. 单个参数(不需要括号):

    const square = x => x * x;
    
  3. 多个参数(需要括号):

    const add = (a, b) => a + b;
    
  4. 多行语句(使用花括号 {} 并且需要 return 语句):

    const multiply = (a, b) => {
        const result = a * b;
        return result;
    };
    
  5. 返回对象字面量(需要使用括号 () 包裹对象):

    const createPerson = (name, age) => ({
        name: name,
        age: age
    });
    

特性

  1. this 绑定

    • 箭头函数不绑定自己的 this,而是继承外层作用域的 this。这对于避免在回调函数中出现 this 指向问题非常有用。
    function Timer() {
        this.seconds = 0;
        setInterval(() => {
            this.seconds++;
            console.log(this.seconds);
        }, 1000);
    }
    ​
    new Timer(); // 正确输出秒数
    
  2. 不能用作构造函数

    • 箭头函数不能用作构造函数,不能使用 new 关键字。
    const Person = (name) => {
        this.name = name;
    };
    ​
    // const person = new Person('Alice'); // 报错
    
  3. 没有 arguments 对象

    • 箭头函数没有 arguments 对象,如果需要使用 arguments,可以使用传统的函数表达式或通过 rest 参数来处理。
    function showArguments() {
        console.log(arguments);
    }
    ​
    const showArgs = () => {
        console.log(arguments); // 报错,箭头函数没有 arguments 对象
    };
    
  4. 没有 supernew.target

    • 箭头函数没有 supernew.target,因此不能在继承或构造函数中使用这些特性。

适用场景

  • 简洁的回调函数:箭头函数适合用于简洁的回调函数,例如数组的 mapfilterreduce 等方法。

    const numbers = [1, 2, 3];
    const squares = numbers.map(n => n * n);
    console.log(squares); // [1, 4, 9]
    
  • 函数体简单的情况:如果函数体很简单,且只包含一个表达式,可以使用箭头函数来简化代码。

限制

  • 无法作为构造函数:如前所述,箭头函数不能被用作构造函数。
  • 无法使用 arguments 对象:如果需要处理 arguments,需要使用传统函数。
  • 不适合处理 this 需要动态绑定的场景:在需要动态绑定 this 的场景,箭头函数可能不适合,因为它总是继承外层 this

总结

  • 简洁的语法:箭头函数语法比传统函数更简洁,适用于函数体简单的情况。
  • this 绑定:箭头函数不绑定自己的 this,继承外层作用域的 this,适合用于回调函数。
  • 限制:箭头函数不能用作构造函数,没有 arguments 对象,不适合动态绑定 this 的场景。

箭头函数是现代 JavaScript 编程中非常有用的特性,它可以提高代码的可读性,并减少样板代码。在使用时,需要注意它的限制和适用场景,以便在合适的情况下发挥其最大效用。