10 个 JavaScript 棘手技巧
共 25250字,需浏览 51分钟
·
2024-04-11 11:49
本文适合对JavaScript小技巧感兴趣的小伙伴阅读。
欢迎关注 前端早茶 ,与广东靓仔携手共同进阶~
一、前言
你准备好学习很酷的 JavaScript 技巧了吗?这些技巧将使您的代码更好、更容易理解、编写速度更快。在这篇文章中,我们将探索隐藏的功能和快捷方式,帮助您释放 JavaScript 的全部威力! 本文分为3部分的10个JavaScript 棘手技巧第一部分
1. 空合并运算符 (??)
空合并运算符 (??) 是一个逻辑运算符,当其左侧操作数为 null 或未定义时,它返回其右侧操作数,否则返回其左侧操作数。当您想要为可能为 null 或未定义的变量提供默认值时,这会很有用。
这是一个简单的代码示例:
let value = null;
let defaultValue = "Default Value";
let result = value ?? defaultValue;
console.log(result); // Outputs: "Default Value"
在此示例中,由于 value 为 null,因此 nullish 合并运算符返回 defaultValue,因此“默认值”会记录到控制台。
如果 value 不为 null 或未定义,则会返回该值:
let value = "Not Null Value";
let defaultValue = "Default Value";
let result = value ?? defaultValue;
console.log(result); // Outputs: "Not Null Value"
在本例中,由于 value 既不是 null 也不是未定义的,所以它是由 nullish 合并运算符返回的,因此“Not Null Value”会记录到控制台。
2. 可选链接 (?.)
如果引用为空,则可以安全地访问嵌套对象属性,而不会出现错误。这 ?。运算符的功能与 . 链接运算符,不同之处在于,如果引用为空(空或未定义),则表达式会短路并返回未定义的值,而不是导致错误。
这是一个简单的代码示例:
let user = {
name: "John",
address: {
street: "Main",
city: "New York"
}
};
console.log(user.address.street); // Outputs: "Main"
let user2 = {
name: "Jane"
};
console.log(user2.address?.street); // Outputs: undefined
在此示例中,由于 user2 没有 address 属性,因此尝试访问 user2.address.street 通常会导致 TypeError。但是,通过使用可选链接运算符 (?.),JavaScript 只会返回 undefined 而不是抛出错误。
3. 短路评估
JavaScript 中的短路求值是一种求值布尔表达式的方法。如果表达式中的第一个操作数足以确定最终结果,则不计算第二个操作数。这通常与 && (AND) 和 || 一起使用。(或)运算符。
这是一个简单的代码示例:
let a = 0;
let b = 1;
// Using && operator
console.log(a && b); // Outputs: 0
在此示例中,使用 && 运算符。对于 AND 运算,如果第一个操作数为 false(或像 0 这样的假值),JavaScript 不需要检查第二个操作数,因为无论如何结果都将为 false。这就是为什么它输出 0 - 它“短路”并且不评估 b。
let c = 1;
let d = 2;
// Using || operator
console.log(c || d); // Outputs: 1
在第二个示例中,|| 使用运算符。对于 OR 运算,如果第一个操作数为 true(或真值),JavaScript 不需要检查第二个操作数,因为无论如何结果都将为 true。这就是为什么它输出 1 - 它“短路”并且不评估 d。
4. 使用map、filter和reduce进行数组操作
让我们分解一下这些方法:
-
map():此方法创建一个新数组,其中包含对数组中每个元素调用提供的函数的结果。
let numbers = [1, 2, 3, 4, 5];
let squares = numbers.map(num => num * num);
console.log(squares); // Outputs: [1, 4, 9, 16, 25]
在此示例中,map() 用于对数字数组中的每个数字求平方。
-
filter():此方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素
let numbers = [1, 2, 3, 4, 5];
let evens = numbers.filter(num => num % 2 === 0);
console.log(evens); // Outputs: [2, 4]
在此示例中,filter() 用于创建一个仅包含numbers 数组中的偶数的新数组。
-
reduce():此方法对累加器和数组中的每个元素(从左到右)应用函数,以将其减少为单个输出值。
let numbers = [1, 2, 3, 4, 5];
let sum = numbers.reduce((total, num) => total + num, 0);
console.log(sum); // Outputs: 15
在此示例中,reduce() 用于对数字数组中的所有数字求和。reduce() 的第二个参数(在本例中为 0)是累加器的初始值(在本例中为总计)。
这些方法通常组合使用来执行复杂的数组操作。例如,您可以首先使用filter()仅获取偶数,然后使用map()对这些数字进行平方,最后使用reduce()对平方求和:
let numbers = [1, 2, 3, 4, 5];
let sumOfEvenSquares = numbers
.filter(num => num % 2 === 0)
.map(num => num * num)
.reduce((total, num) => total + num, 0);
console.log(sumOfEvenSquares); // Outputs: 20
在此示例中,输出为 20,因为 2*2 + 4*4 = 4 + 16 = 20。
5. 使用!! 转换为布尔值
在 JavaScript 中,!! 运算符用于将值转换为布尔值。首先 !否定该值,将其转换为布尔值并将其反转,第二个 ! 将其反转回其原始布尔值。
这是一个简单的代码示例:
let truthyValue = "Hello, World!";
let falseyValue = "";
console.log(!!truthyValue); // Outputs: true
console.log(!!falseyValue); // Outputs: false
在此示例中,truthyValue 是一个非空字符串,在 JavaScript 中被视为 true 值,因此 !!truthyValue 返回 true。另一方面, falseyValue 是一个空字符串,在 JavaScript 中被视为 falsey 值,因此 !!falseyValue 返回 false。
6. 短 if-else 的三元运算符
三元运算符是许多编程语言(包括 JavaScript)中编写 if-else 语句的简写方式。之所以称为三元运算符,是因为它需要三个操作数:一个条件、条件为真时的结果以及条件为假时的结果。
语法如下:
condition ? valueIfTrue : valueIfFalse
这是一个简单的代码示例:
let age = 15;
let beverage = (age >= 21) ? "Beer" : "Juice";
console.log(beverage); // Outputs: "Juice"
在此示例中,条件是年龄 >= 21。如果此条件为真,则饮料变量将设置为“Beer”。如果条件为假,则饮料设置为“Juice”。由于年龄为 15,不大于或等于 21,因此条件为 false,因此饮料设置为“Juice”。
7. 默认功能参数
默认函数参数允许您设置函数参数的默认值。这意味着如果调用函数时没有为形参提供实参,则将使用默认值。JavaScript ES6 及更高版本中提供此功能。
语法如下:
function functionName(param1 = defaultValue1, param2 = defaultValue2, ...) {
// function body
}
这是一个简单的代码示例:
function greet(name = "Stranger") {
return "Hello, " + name;
}
console.log(greet()); // Outputs: "Hello, Stranger"
console.log(greet("John")); // Outputs: "Hello, John"
在此示例中,函数greet 有一个参数名称,默认值为“Stranger”。如果您不带任何参数调用greet(),则name参数将采用其默认值,并且该函数将输出“Hello,Stranger”。如果调用greet("John"),name参数将采用值“John”,并且该函数将输出“Hello, John”。
8. 动态字符串的模板文字
模板文字是 JavaScript 中的一项功能,允许您以更加动态和可读的方式创建字符串。它们是使用反引号 ( ) 而不是单引号或双引号来定义的。
在模板文字中,您可以在 ${} 中包含表达式、变量和其他 JavaScript 代码。JavaScript 引擎将评估 ${} 内的代码并将其结果插入到字符串中。这使得创建复杂的字符串变得容易,而无需使用 + 运算符连接字符串的各个部分。
这是一个简单的代码示例:
let name = "John";
let greeting = `Hello, ${name}!`;
console.log(greeting); // Outputs: "Hello, John!"
在此示例中,使用 ${name} 将变量名称插入到模板文字中。JavaScript 引擎计算 name,将 ${name} 替换为 name 的值,然后创建最终的字符串。
您还可以在 ${} 内使用表达式。这是一个例子:
let a = 5;
let b = 10;
let sum = `The sum of ${a} and ${b} is ${a + b}.`;
console.log(sum); // Outputs: "The sum of 5 and 10 is 15."
在此示例中,计算表达式 a + b 并将其结果插入到字符串中。
9. 解构赋值
解构赋值是 JavaScript 中的一项功能,它允许您将数组中的值或对象中的属性解压到不同的变量中。这可以使您的代码更具可读性和简洁性。
这是一个数组的示例:
let numbers = [1, 2, 3];
let [a, b, c] = numbers;
console.log(a); // Outputs: 1
console.log(b); // Outputs: 2
console.log(c); // Outputs: 3
在此示例中,变量 a、b 和 c 分别被赋予 number 数组的第一个、第二个和第三个元素的值。
解构也可以用于对象:
let person = {
name: "John",
age: 30,
city: "New York"
};
let {name, age, city} = person;
console.log(name); // Outputs: "John"
console.log(age); // Outputs: 30
console.log(city); // Outputs: "New York"
在此示例中,变量 name、age 和 city 被分配为 person 对象中相应属性的值。
10. 用于数组和对象克隆的扩展运算符
JavaScript 中的展开运算符 (...) 用于将可迭代对象(如数组或对象)的元素展开为单独的元素。当您想要克隆数组或对象时,这尤其有用。
这是一个数组的示例:
let originalArray = [1, 2, 3];
let clonedArray = [...originalArray];
console.log(clonedArray); // Outputs: [1, 2, 3]
在此示例中,cloneArray 是一个新数组,其中包含originalArray 的所有元素。对originalArray 的任何更改都不会影响clonedArray,反之亦然。
扩展运算符也可用于克隆对象:
let originalObject = {
name: "John",
age: 30,
city: "New York"
};
let clonedObject = {...originalObject};
console.log(clonedObject); // Outputs: { name: 'John', age: 30, city: 'New York' }
在此示例中,clonedObject 是一个新对象,包含originalObject 的所有属性。对originalObject 的任何更改都不会影响clonedObject,反之亦然。
扩展运算符还可以用于合并数组或对象:
let array1 = [1, 2, 3];
let array2 = [4, 5, 6];
let mergedArray = [...array1, ...array2];
console.log(mergedArray); // Outputs: [1, 2, 3, 4, 5, 6]
let object1 = {a: 1, b: 2};
let object2 = {c: 3, d: 4};
let mergedObject = {...object1, ...object2};
console.log(mergedObject); // Outputs: { a: 1, b: 2, c: 3, d: 4 }
在这些示例中, mergedArray 和 mergedObject 分别包含 array1 和 array2 或 object1 和 object2 的元素或属性。
第二部分
1. 标记模板文字
标记模板文字是 JavaScript 中模板文字的更高级形式。它们允许您使用函数解析模板文字。标签函数的第一个参数包含一个字符串值数组。其余参数与表达式相关。
这是一个简单的例子:
function tag(strings, ...values) {
console.log(strings);
console.log(values);
}
let name = "John";
let age = 30;
tag`Hello, my name is ${name} and I am ${age} years old.`;
在这个例子中,标签函数是我们的标签模板。当我们使用模板文字调用此函数时,它会被拆分为字符串和值的数组。strings 数组包含模板文字的所有字符串部分(“Hello,我的名字是”,“,我是”,“岁。”),values 数组包含计算的表达式(姓名,年龄)。
该代码的输出将是:
[ 'Hello, my name is ', ' and I am ', ' years old.' ]
[ 'John', 30 ]
当您想要创建一个函数来生成特定类型的文本输出,并具有如何将值插入字符串的复杂规则时,此功能非常有用。
2. 唯一元素的集合对象
在 JavaScript 中,Set 对象是一个内置对象,它存储任何类型的唯一值,无论是原始值还是对象引用。Set中的一个值只能出现一次;它在套装系列中是独一无二的。
以下是如何使用 Set 的简单示例:
let mySet = new Set();
mySet.add(1); // Add a number
mySet.add('some text'); // Add a string
mySet.add('some text'); // Try to add the same string again
console.log(mySet);
在此示例中,我们创建一个新 Set 并向其中添加一个数字和一个字符串。当我们尝试再次添加相同的字符串时,它不会被添加,因为它已经在集合中了。console.log 语句的输出将是:
Set(2) { 1, 'some text' }
这表明该 Set 包含两个元素:数字 1 和字符串“some text”。重复的字符串未添加到集合中。
您还可以从数组创建一个 Set,它会自动删除任何重复的值:
let array = [1, 2, 3, 4, 4, 5, 5, 5];
let mySet = new Set(array);
console.log(mySet); // Output: Set(5) { 1, 2, 3, 4, 5 }
在此示例中,数组包含重复的数字。当我们从此数组创建 Set 时,它会自动删除重复项,因此 Set 仅包含数组中的唯一数字。
3.使用Object.entries()和Object.fromEntries()
a) 对象.entries()
Object.entries() 是一种方法,它返回给定对象自己的可枚举字符串键控属性 [key, value] 对的数组,其顺序与 for...in 循环提供的顺序相同。唯一重要的区别是 for...in 循环也枚举原型链中的属性。
这是一个例子:
let obj = { foo: 'bar', baz: 42 };
console.log(Object.entries(obj)); // Output: [ ['foo', 'bar'], ['baz', 42] ]
在此示例中,Object.entries() 用于将对象转换为键值对数组。
b) Object.fromEntries()
Object.fromEntries() 执行 Object.entries() 的逆操作。它将键值对列表转换为对象。
这是一个例子:
let entries = [ ['foo', 'bar'], ['baz', 42] ];
let obj = Object.fromEntries(entries);
console.log(obj); // Output: { foo: 'bar', baz: 42 }
在此示例中,Object.fromEntries() 用于将键值对数组转换回对象。
4. 对象中的动态属性名称
在 JavaScript 中,您可以使用计算属性名称在对象中创建动态属性名称。这是通过将表达式括在方括号 [] 中来完成的,该表达式将被计算为属性名称。当您需要动态创建属性名称时,这非常有用。
这是一个例子:
let dynamicKey = 'name';
let obj = {
[dynamicKey]: 'John Doe'
};
console.log(obj); // Output: { name: 'John Doe' }
在本例中,变量dynamicKey用作对象obj的属性名称。DynamicKey 的值为“name”,因此该对象最终会得到一个名为“name”且值为“John Doe”的属性。
您还可以使用此功能创建具有更复杂名称的属性:
let prefix = 'prop';
let obj = {
[`${prefix}_name`]: 'John Doe',
[`${prefix}_age`]: 30
};
console.log(obj); // Output: { prop_name: 'John Doe', prop_age: 30 }
在此示例中,属性名称是通过将前缀变量与“_name”和“_age”连接起来创建的。生成的对象具有属性“prop_name”和“prop_age”。
5. 使用bind()进行函数柯里化
函数柯里化是 JavaScript 中的一种技术,其中具有多个参数的函数被转换为一系列函数,每个函数都具有单个参数。这可以使用bind()方法来实现。
这是一个例子:
function multiply(a, b) {
return a * b;
}
let multiplyByTwo = multiply.bind(this, 2);
console.log(multiplyByTwo(4)); // Output: 8
此示例中,乘法函数采用两个参数。我们通过在乘法上调用bind()来创建一个新函数multiplyByTwo。bind() 的第一个参数是 this 值,我们不需要更改它,因此我们传递 this。第二个参数是要进行乘法的第一个参数,我们将其固定为 2。现在,multiplyByTwo 是一个函数,它接受单个参数,将其乘以 2,然后返回结果。
6. 使用 Array.from() 从类数组对象创建数组
在 JavaScript 中,Array.from() 是一种静态方法,它从类似数组或可迭代的对象创建新的浅复制数组实例。
这是一个例子:
let arrayLike = { length: 2, 0: 'a', 1: 'b' };
let arr = Array.from(arrayLike);
console.log(arr); // Output: ['a', 'b']
在此示例中,arrayLike 是一个具有与数组类似的属性和长度的对象,但它不是数组。Array.from() 用于将这个类似数组的对象转换为真正的数组。
当您想从字符串创建数组时,Array.from() 也很有用:
let str = 'hello';
let arr = Array.from(str);
console.log(arr); // Output: ['h', 'e', 'l', 'l', 'o']
在此示例中,Array.from() 用于将字符串转换为单个字符的数组。
7. 可迭代对象的 for...of 循环
for...of 循环是一个 JavaScript 语句,允许您迭代可迭代对象,例如数组、字符串、映射、集合等。它是传统 for 循环的更简洁、更易读的替代方案。
下面是一些代码示例
a) 您可以使用 for...of 循环来迭代数组:
let fruits = ['apple', 'banana', 'cherry'];
for (let fruit of fruits) {
console.log(fruit);
}
在此示例中,for...of 循环迭代fruits 数组中的每个元素并将其记录到控制台。输出将是:
apple
banana
cherry
b) 您还可以使用 for...of 循环来迭代字符串:
let greeting = 'Hello';
for (let char of greeting) {
console.log(char);
}
在此示例中,for...of 循环迭代问候语字符串中的每个字符并将其记录到控制台。输出将是:
H
e
l
l
o
请记住,for...of 循环适用于可迭代对象,这意味着它不适用于常规对象,除非它们可迭代。
8. 使用 Promise.all() 实现并发 Promise
Promise.all() 是 JavaScript 中的一种方法,用于同时处理多个 Promise。它采用可迭代的 Promise 作为输入,并返回一个 Promise,当所有输入的 Promise 都已解决时,该 Promise 会被解析,或者会因第一个 Promise 被拒绝的原因而被拒绝。
这是一个例子:
let promise1 = Promise.resolve(3);
let promise2 = 42;
let promise3 = new Promise((resolve, reject) => {
setTimeout(resolve, 100, 'foo');
});
Promise.all([promise1, promise2, promise3]).then((values) => {
console.log(values); // Output: [3, 42, "foo"]
});
示例中,Promise.all() 用于同时处理三个 Promise。Promise1 是一个 Promise,解析值为 3,promise2 是一个非 Promise 值 42,promise3 是一个 Promise,在 100 毫秒后解析值为 'foo'。
Promise.all([promise1,promise2,promise3]) 返回一个新的 Promise,当所有输入的 Promise 都已解析时,该 Promise 才会解析。解析值是输入 Promise 解析值的数组,其顺序与输入 Promise 相同。在本例中,解析的值为 [3, 42, "foo"]。
如果任何输入的 Promise 被拒绝,则 Promise.all() 返回的 Promise 会立即拒绝,并给出第一个被拒绝的 Promise 的原因,而无需等待其他 Promise 解决或拒绝。
9. 函数参数的剩余参数
剩余参数语法允许我们将不定数量的参数表示为数组。当编写可以接受任意数量参数的函数时,这尤其有用。
这是一个例子:
function sum(...args) {
let total = 0;
for(let arg of args) {
total += arg;
}
return total;
}
console.log(sum(1, 2, 3, 4)); // Output: 10
console.log(sum(1, 2, 3, 4, 5)); // Output: 15
使用剩余参数语法 (...args) 将其所有参数收集到一个数组中。然后,它使用 for...of 循环迭代数组并将所有数字相加。可以使用任意数量的参数调用该函数,并且它将返回所有参数的总和。
10. 用于性能优化的记忆
记忆化是一种编程技术,主要用于通过存储昂贵的函数调用的结果并在相同的输入再次出现时重用它们来加速计算机程序。该技术用于一次又一次解决相同子问题的优化问题。
以下示例展示了如何在 JavaScript 中使用记忆化来优化计算斐波那契数的递归函数:
let memo = {};
function fib(n) {
if (n <= 1) {
return n;
} else if (memo[n]) {
return memo[n];
} else {
memo[n] = fib(n - 1) + fib(n - 2);
return memo[n];
}
}
console.log(fib(10)); // Output: 55
console.log(fib(20)); // Output: 6765
在此示例中,fib 函数首先检查给定输入 n 的结果是否已存储在 memo 对象中。如果是,该函数将返回存储的结果,从而避免执行昂贵的递归调用。如果结果尚未存储,该函数将使用斐波那契数列的递归公式计算结果,将其存储在 memo 对象中,然后返回。这样,该函数就可以避免一遍又一遍地重新计算相同的斐波那契数,从而显着提高了大输入的性能。
第三部分
1. 使用 flat() 展平数组
JavaScript 中的 flat() 方法用于展平数组。它创建一个新数组,其中所有子数组元素递归地连接到指定深度。默认情况下,深度为 1。
这是一个例子:
let arr = [1, 2, [3, 4, [5, 6]]];
console.log(arr.flat());
// Output: [1, 2, 3, 4, [5, 6]]
console.log(arr.flat(2));
// Output: [1, 2, 3, 4, 5, 6]
console.log(arr.flat(Infinity));
// Output: [1, 2, 3, 4, 5, 6]
在第一个 console.log 中,我们在不带任何参数的情况下调用 flat(),因此它的深度默认为 1,并且只有第一层嵌套数组会被展平。
在第二个 console.log 中,我们调用 flat(2),指定深度为 2,因此它会展平最多两层嵌套数组。
在第三个console.log中,通过传递Infinity,它将展平所有嵌套数组,无论它们有多深。
2. 使用 ^ 交换值
JavaScript 中的插入符号 (^) 用于按位异或运算。但是,它也可以用于在两个变量之间交换值,而无需使用临时变量。它的工作原理如下:
let a = 5; // binary: 101
let b = 3; // binary: 011
a = a ^ b; // binary: 110, decimal: 6
b = a ^ b; // binary: 101, decimal: 5
a = a ^ b; // binary: 011, decimal: 3
经过这些操作,a 变为 3,b 变为 5,有效地交换了它们的原始值。
解释如下:
-
a = a ^ b 对 a 和 b 进行按位异或运算,并将结果赋给 a。现在 a 保存了 a ^ b 的结果。
-
b = a ^ b 等价于 b = (a ^ b) ^ b。由于 XOR 是结合律,因此等价于 b = a ^ (b ^ b)。b ^ b 为 0,任何数字 XOR 0 就是该数字本身,因此 b 变为 a。
-
a = a ^ b 等价于 a = (a ^ b) ^ a。这相当于a=b^(a^a)。a ^ a 为 0,因此 a 变为 b。
因此,a 和 b 的值在不使用临时变量的情况下被交换。但是,应谨慎使用此方法,因为如果 a 和 b 不是整数或者它们非常大,则可能会导致意外结果。
3. 用一元加法转换为数字
在 JavaScript 中,一元加号 (+) 运算符可用于将字符串或布尔值转换为数字。这是在 JavaScript 中执行类型转换的一种快速且简单的方法。它的工作原理如下:
let str = "123";
let num = +str; // num is now the number 123
console.log(typeof str); // "string"
console.log(typeof num); // "number"
let bool = true;
let numFromBool = +bool; // numFromBool is now the number 1
console.log(typeof bool); // "boolean"
console.log(typeof numFromBool); // "number"
在上面的示例中,一元加运算符用于将字符串和布尔值转换为数字。将字符串“123”转换为数字123,将布尔值true转换为数字1。使用typeof运算符来确认转换前后变量的类型。
需要注意的是,如果字符串无法解析为数字,则结果将为 NaN(不是数字):
let str = "abc";
let num = +str; // num is now NaN
console.log(num); // NaN
在这种情况下,字符串“abc”无法解析为数字,因此一元加运算的结果为NaN。
4. 使用 Object.assign() 合并对象
在 JavaScript 中,Object.assign() 是一种用于将所有可枚举自身属性的值从一个或多个源对象复制到目标对象的方法。它将返回目标对象。此方法通常用于合并对象(组合两个或多个对象的属性)。
这是一个例子:
let obj1 = { a: 1, b: 2 };
let obj2 = { b: 3, c: 4 };
let mergedObj = Object.assign({}, obj1, obj2);
console.log(mergedObj); // { a: 1, b: 3, c: 4 }
在此示例中,Object.assign() 采用三个参数:空对象 {}、obj1 和 obj2。首先将 obj1 中的所有属性复制到空对象。然后它将所有属性从 obj2 复制到目标对象。如果目标对象上已存在某个属性(如本例中的 b),则其值将被源对象 (obj2) 中的值覆盖。
因此,生成的 mergedObj 包含 obj1 和 obj2 中的所有属性,其中 obj2 中的值优先。
5. 默认值短路
在 JavaScript 中,您可以使用逻辑 OR (||) 运算符为变量提供默认值。这种技术称为短路。如果 || 左侧的值 运算符为真(即,在布尔上下文中计算时被视为 true 的值),它将是结果。如果它是假的(即,在布尔上下文中计算时被视为假的值),则 || 右侧的值 运算符将是结果。
这是一个例子:
let name = user.name || 'Anonymous';
console.log(name); // If user.name exists and is not an empty string, null, undefined, 0, NaN, or false, it will be logged. Otherwise, 'Anonymous' will be logged.
在此示例中,如果定义了 user.name 并且不是空字符串、null、undefined、0、NaN 或 false,则 name 将被赋予 user.name 的值。如果 user.name 未定义或者是这些虚假值之一,则 name 将被分配字符串“Anonymous”。
这称为短路,因为如果第一个操作数为真,JavaScript 甚至不会查看第二个操作数 - 它会“短路”操作并返回第一个操作数。
6. 使用括号表示法动态访问对象属性
在 JavaScript 中,您可以使用括号表示法动态访问对象属性。当您需要访问名称存储在变量中的属性时,或者当属性名称不是有效的标识符(例如,它包含空格或特殊字符)时,这特别有用。
这是一个例子:
let person = {
name: 'John',
age: 30,
'favorite color': 'blue'
};
let property = 'name';
console.log(person[property]); // Outputs: 'John'
property = 'age';
console.log(person[property]); // Outputs: 30
console.log(person['favorite color']); // Outputs: 'blue'
我们首先定义一个具有名称、年龄和最喜欢的颜色属性的对象 person。然后我们定义一个变量属性并将其设置为“name”。当我们使用 person[property] 时,JavaScript 会查找属性的值(即“name”),然后从 person 对象中检索属性“name”的值。我们可以将属性的值更改为“age”并以相同的方式访问age属性。我们还可以直接使用括号中的字符串来访问名称不是有效标识符的属性,例如“最喜欢的颜色”。
7. HTML 片段的模板字符串
模板字符串,也称为模板文字,是 JavaScript 中的一项功能,允许您创建带有嵌入表达式的字符串。它们在创建 HTML 片段时特别有用,因为它们允许您轻松地将变量和表达式插入到 HTML 中。
这是一个例子:
let name = 'John';
let age = 30;
let html = `
<div>
<h1>${name}</h1>
<p>Age: ${age}</p>
</div>`
;
console.log(html);
在这个例子中,我们首先定义两个变量name和age。然后我们定义一个包含 HTML 片段的模板字符串 html。模板字符串用反引号括起来,变量名称和年龄使用 ${...} 语法插入到 HTML 中。当我们将 html 记录到控制台时,它会输出以下 HTML:
<div>
<h1>John</h1>
<p>Age: 30</p>
</div>
TML 时(例如,根据服务器数据构建网页时),此功能非常有用。
8. 使用 Array.includes() 进行存在检查
JavaScript 中的 Array.includes() 方法用于确定数组的条目中是否包含某个值。它根据需要返回 true 或 false。
这是一个例子:
let array = [1, 2, 3, 4, 5];
console.log(array.includes(2)); // Outputs: true
console.log(array.includes(6)); // Outputs: false
在此示例中,我们有一个从 1 到 5 的数字数组。然后,我们使用includes() 方法检查数字 2 是否在数组中(确实如此),因此返回 true。我们还检查数字 6 是否在数组中,但事实并非如此,因此返回 false。
9. 防止对象修改
在 JavaScript 中,有多种方法可以防止对象被修改。以下是三种方法:
1. Object.preventExtensions(): 该方法阻止向对象添加新属性。
let obj = { a: 1 };
Object.preventExtensions(obj);
obj.b = 2; // Attempt to add new property
console.log(obj.b); // Outputs: undefined
2. Object.seal(): 该方法防止添加新属性和删除现有属性。但是,它允许修改现有属性。
let obj = { a: 1 };
Object.seal(obj);
obj.b = 2; // Attempt to add new property
delete obj.a; // Attempt to delete existing property
console.log(obj.b); // Outputs: undefined
console.log(obj.a); // Outputs: 1
3. Object.freeze(): 该方法防止添加新属性、删除现有属性,并防止更改现有属性的可枚举性、可配置性或可写性。本质上,它使对象变为只读。
let obj = { a: 1 };
Object.freeze(obj);
obj.b = 2; // Attempt to add new property
obj.a = 3; // Attempt to modify existing property
console.log(obj.b); // Outputs: undefined
console.log(obj.a); // Outputs: 1
在所有这些示例中,尝试以不允许的方式修改对象不会引发错误,它根本不会产生任何效果。然而,在严格模式下('use strict';),这些操作将抛出 TypeError。
10. Function.prototype.bind() 的强大功能
JavaScript 中的 Function.prototype.bind() 方法是一个强大的工具,它允许您在函数的上下文中设置 this 值,并使用特定的 this 值和初始参数创建一个新函数。
这是一个例子:
let person = {
firstName: "John",
lastName: "Doe",
fullName: function() {
return this.firstName + " " + this.lastName;
}
}
let logName = function(location, country) {
console.log(this.fullName() + " from " + location + ", " + country);
}
// Create a new function with 'this' bound to 'person'
let logPersonName = logName.bind(person);
// Call the new function
logPersonName("New York", "USA"); // Outputs: "John Doe from New York, USA"
有 fullName 方法的 person 对象。我们还有一个 logName 函数,用于记录一条消息,其中包括该人的全名和位置。
然后我们使用bind()创建一个新函数logPersonName,它被绑定到person对象。当我们调用 logPersonName 时,它可以访问 person 对象的 fullName 方法,因为它被设置为 person。
当您想要从对象借用方法,或者想要拥有一个可以与不同 this 值一起使用的函数时,这特别有用。
原文链接:https://dev.to/sayuj/10-javascript-tricky-hacks-part-1-52dl文章转载于:萨尤吉·塞加尔
最后
这些技巧希望对小伙伴们日常开发帮忙有所帮助~
关注我,一起携手进阶
欢迎关注前端早茶,与广东靓仔携手共同进阶~