文章目录
- ecmascript 历程
- 严格模式与常规模式下的区别及注意事项
- 严格模式下的属性删除
- Array.prototype.flat()和Array.prototype.flatMap() 实例应用
ecmascript 历程
-
变量声明要求
- 常规模式:
- 在常规模式下,使用
var
关键字声明变量时会出现变量提升现象。这意味着变量可以在声明之前使用,并且会被自动提升到函数作用域的顶部。例如:
function test() { console.log(x); var x = 10; } test();
- 上述代码在常规模式下,
console.log(x)
不会报错,而是输出undefined
。因为JavaScript引擎会将var x
提升到函数顶部,代码实际上被解释为:
function test() { var x; console.log(x); x = 10; } test();
- 在常规模式下,使用
- 严格模式:
- 在严格模式下(
'use strict'
),不允许使用未声明的变量。如果这样做,会直接抛出引用错误。例如:
"use strict"; function test() { console.log(x); var x = 10; } test();
- 这段代码在严格模式下会抛出
ReferenceError: x is not defined
错误。严格模式强制要求变量先声明后使用,这样可以避免因变量未声明而导致的潜在错误,使得代码更加健壮。
- 在严格模式下(
- 常规模式:
-
函数参数重复命名
- 常规模式:
- 在常规模式下,函数参数可以有重复的名称,后面的参数会覆盖前面同名的参数。例如:
function add(a, a) { return a + a; } console.log(add(2, 3));
- 上述代码在常规模式下会输出
6
,因为第二个a
(值为3
)覆盖了第一个a
(值为2
)。
- 严格模式:
- 在严格模式下,不允许函数参数有重复的名称。如果出现这种情况,会抛出语法错误。例如:
"use strict"; function add(a, a) { return a + a; } console.log(add(2, 3));
- 这段代码在严格模式下会抛出
SyntaxError: Duplicate parameter name not allowed in this context
错误。
- 常规模式:
-
对象属性操作
- 常规模式:
- 在常规模式下,可以通过
delete
操作符删除不可配置的属性,虽然在严格模式下会返回false
,但在常规模式下不会报错。例如:
var obj = {}; Object.defineProperty(obj, 'prop', {value: 10, configurable: false}); console.log(delete obj.prop);
- 上述代码在常规模式下会输出
false
,但不会抛出错误。
- 在常规模式下,可以通过
- 严格模式:
- 在严格模式下,试图删除不可配置的属性会抛出类型错误。例如:
"use strict"; var obj = {}; Object.defineProperty(obj, 'prop', {value: 10, configurable: false}); console.log(delete obj.prop);
- 这段代码在严格模式下会抛出
TypeError: Cannot delete property 'prop' of #<Object>
错误。
- 常规模式:
-
函数的
this
指向- 常规模式:
- 在常规模式下,函数中的
this
指向可能会出现一些不符合预期的情况。例如,在全局函数中,this
通常指向全局对象(在浏览器环境中是window
)。
function test() { console.log(this); } test();
- 在浏览器环境下,上述代码会输出
window
对象。并且在一些事件处理函数中,如果没有正确绑定this
,它的指向也可能会出现问题。
- 在常规模式下,函数中的
- 严格模式:
- 在严格模式下,函数中的
this
不会自动指向全局对象。如果this
没有被明确的对象调用,它的值为undefined
。例如:
"use strict"; function test() { console.log(this); } test();
- 这段代码在严格模式下会输出
undefined
,这使得函数内部this
的行为更加可预测,避免了一些由于this
指向混乱而导致的错误。
- 在严格模式下,函数中的
- 常规模式:
-
应用注意点
- 谨慎转换现有代码:如果要将现有的JavaScript代码转换为严格模式,需要仔细检查代码中是否存在不符合严格模式要求的部分,如未声明的变量、重复的函数参数等,否则可能会导致大量错误。
- 模块和库使用:在开发模块和库时,严格模式可以帮助确保代码的质量和稳定性。因为模块和库通常会被多个项目使用,严格模式下的严格检查可以减少潜在的错误。
- 团队协作和代码维护:在团队开发环境中,提倡使用严格模式可以使代码风格更加统一,便于团队成员理解和维护代码。因为严格模式的规则更加明确,减少了一些JavaScript中可能出现的模糊和易错的情况。
严格模式与常规模式下的区别及注意事项
-
变量声明要求
- 常规模式:
- 在常规模式下,使用
var
关键字声明变量时会出现变量提升现象。这意味着变量可以在声明之前使用,并且会被自动提升到函数作用域的顶部。例如:
function test() { console.log(x); var x = 10; } test();
- 上述代码在常规模式下,
console.log(x)
不会报错,而是输出undefined
。因为JavaScript引擎会将var x
提升到函数顶部,代码实际上被解释为:
function test() { var x; console.log(x); x = 10; } test();
- 在常规模式下,使用
- 严格模式:
- 在严格模式下(
'use strict'
),不允许使用未声明的变量。如果这样做,会直接抛出引用错误。例如:
"use strict"; function test() { console.log(x); var x = 10; } test();
- 这段代码在严格模式下会抛出
ReferenceError: x is not defined
错误。严格模式强制要求变量先声明后使用,这样可以避免因变量未声明而导致的潜在错误,使得代码更加健壮。
- 在严格模式下(
- 常规模式:
-
函数参数重复命名
- 常规模式:
- 在常规模式下,函数参数可以有重复的名称,后面的参数会覆盖前面同名的参数。例如:
function add(a, a) { return a + a; } console.log(add(2, 3));
- 上述代码在常规模式下会输出
6
,因为第二个a
(值为3
)覆盖了第一个a
(值为2
)。
- 严格模式:
- 在严格模式下,不允许函数参数有重复的名称。如果出现这种情况,会抛出语法错误。例如:
"use strict"; function add(a, a) { return a + a; } console.log(add(2, 3));
- 这段代码在严格模式下会抛出
SyntaxError: Duplicate parameter name not allowed in this context
错误。
- 常规模式:
-
对象属性操作
- 常规模式:
- 在常规模式下,可以通过
delete
操作符删除不可配置的属性,虽然在严格模式下会返回false
,但在常规模式下不会报错。例如:
var obj = {}; Object.defineProperty(obj, 'prop', {value: 10, configurable: false}); console.log(delete obj.prop);
- 上述代码在常规模式下会输出
false
,但不会抛出错误。
- 在常规模式下,可以通过
- 严格模式:
- 在严格模式下,试图删除不可配置的属性会抛出类型错误。例如:
"use strict"; var obj = {}; Object.defineProperty(obj, 'prop', {value: 10, configurable: false}); console.log(delete obj.prop);
- 这段代码在严格模式下会抛出
TypeError: Cannot delete property 'prop' of #<Object>
错误。
- 常规模式:
-
函数的
this
指向- 常规模式:
- 在常规模式下,函数中的
this
指向可能会出现一些不符合预期的情况。例如,在全局函数中,this
通常指向全局对象(在浏览器环境中是window
)。
function test() { console.log(this); } test();
- 在浏览器环境下,上述代码会输出
window
对象。并且在一些事件处理函数中,如果没有正确绑定this
,它的指向也可能会出现问题。
- 在常规模式下,函数中的
- 严格模式:
- 在严格模式下,函数中的
this
不会自动指向全局对象。如果this
没有被明确的对象调用,它的值为undefined
。例如:
"use strict"; function test() { console.log(this); } test();
- 这段代码在严格模式下会输出
undefined
,这使得函数内部this
的行为更加可预测,避免了一些由于this
指向混乱而导致的错误。
- 在严格模式下,函数中的
- 常规模式:
-
应用注意点
- 谨慎转换现有代码:如果要将现有的JavaScript代码转换为严格模式,需要仔细检查代码中是否存在不符合严格模式要求的部分,如未声明的变量、重复的函数参数等,否则可能会导致大量错误。
- 模块和库使用:在开发模块和库时,严格模式可以帮助确保代码的质量和稳定性。因为模块和库通常会被多个项目使用,严格模式下的严格检查可以减少潜在的错误。
- 团队协作和代码维护:在团队开发环境中,提倡使用严格模式可以使代码风格更加统一,便于团队成员理解和维护代码。因为严格模式的规则更加明确,减少了一些JavaScript中可能出现的模糊和易错的情况。
严格模式下的属性删除
- 可配置属性的删除
- 在严格模式下,如果对象的属性是可配置的(
configurable
为true
),可以使用delete
操作符正常删除属性。 - 例如,创建一个对象并定义一个可配置属性:
"use strict"; let obj = {}; Object.defineProperty(obj, 'prop', { value: 10, configurable: true }); console.log(delete obj.prop); // 输出 true console.log(obj.prop); // 输出 undefined,因为属性已被删除
- 在严格模式下,如果对象的属性是可配置的(
- 不可配置属性的处理
- 如果属性是不可配置的(
configurable
为false
),在严格模式下不能直接使用delete
操作符删除,否则会抛出TypeError
。 - 例如:
"use strict"; let obj = {}; Object.defineProperty(obj, 'prop', { value: 10, configurable: false }); try { console.log(delete obj.prop); } catch (error) { console.log(error); // 输出 TypeError: Cannot delete property 'prop' of #<Object> }
- 若要删除不可配置的属性,需要先将其
configurable
属性修改为true
。这可以通过Object.defineProperty
或者Object.defineProperties
方法来实现。 - 以下是一个修改
configurable
属性后再删除的示例:
"use strict"; let obj = {}; Object.defineProperty(obj, 'prop', { value: 10, configurable: false }); // 先将configurable修改为true Object.defineProperty(obj, 'prop', { configurable: true }); console.log(delete obj.prop); // 输出 true console.log(obj.prop); // 输出 undefined
- 如果属性是不可配置的(
Array.prototype.flat()和Array.prototype.flatMap() 实例应用
-
Array.prototype.flat()
实例应用- 基本功能:
flat()
方法用于将嵌套的数组“扁平化”,即将多维数组转换为一维数组。默认情况下,它会将嵌套一层的数组扁平化,但可以通过传入一个深度参数来指定扁平化的深度。 - 示例一:扁平化一层嵌套数组
- 假设有一个二维数组,代表学生的成绩,每个学生有多门课程的成绩。
let studentScores = [[80, 90], [70, 85], [90, 95]]; let flattenedScores = studentScores.flat(); console.log(flattenedScores);
- 输出结果为
[80, 90, 70, 85, 90, 95]
,将原来的二维数组扁平化成为一个包含所有学生成绩的一维数组。
- 示例二:扁平化多层嵌套数组
- 考虑一个更复杂的情况,有一个多层嵌套的数组。
let multiLevelArray = [[1, 2], [3, [4, 5]]]; let flattenedDeeply = multiLevelArray.flat(2); console.log(flattenedDeeply);
- 这里传入深度参数
2
,因为数组最多嵌套了两层。输出结果为[1, 2, 3, 4, 5]
,成功将多层嵌套的数组扁平化。
- 示例三:处理空数组元素
flat()
方法在扁平化过程中会忽略空数组元素。
let arrayWithEmpty = [[1, 2], [], [3, 4]]; let flattenedWithEmpty = arrayWithEmpty.flat(); console.log(flattenedWithEmpty);
- 输出结果为
[1, 2, 3, 4]
,空数组元素在扁平化后被移除。
- 基本功能:
-
Array.prototype.flatMap()
实例应用- 基本功能:
flatMap()
方法首先对数组中的每个元素应用一个映射函数,然后将结果扁平化。它相当于先执行map()
操作,再执行flat()
操作,但在性能上可能更优,因为它只需要遍历一次数组。 - 示例一:处理字符串数组
- 假设有一个字符串数组,想要将每个字符串拆分成字符数组,然后扁平化得到一个包含所有字符的数组。
let stringArray = ["abc", "def"]; let flattenedChars = stringArray.flatMap(str => str.split('')); console.log(flattenedChars);
- 首先,
map
部分对每个字符串应用split('')
函数,将每个字符串拆分成字符数组,如["abc"]
变成["a", "b", "c"]
。然后flat
部分将这些字符数组扁平化,最终输出结果为["a", "b", "c", "d", "e", "f"]
。
- 示例二:处理对象数组中的属性数组
- 假设你有一个包含用户对象的数组,每个用户对象有一个属性数组,表示用户的兴趣爱好。你想要获取所有用户的所有兴趣爱好。
let users = [ {name: "Alice", hobbies: ["reading", "painting"]}, {name: "Bob", hobbies: ["sports", "music"]} ]; let allHobbies = users.flatMap(user => user.hobbies); console.log(allHobbies);
- 对于每个用户对象,
flatMap
首先通过user.hobbies
获取兴趣爱好数组(这是map
操作),然后将所有这些兴趣爱好数组扁平化,最终输出结果为["reading", "painting", "sports", "music"]
。
- 基本功能: