比较 var 和 let 关键字的作用域
使用 var 关键字声明变量时,它是全局声明的,如果在函数内部声明则是局部声明的。
let 关键字的行为类似,但有一些额外的功能。 在代码块、语句或表达式中使用 let 关键字声明变量时,其作用域仅限于该代码块、语句或表达式。
使用 var 关键字,i 是全局声明的。 所以当 i++ 被执行时,它会更新全局变量。 此代码类似于以下内容:
var numArray = [];
var i;
for (i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
console.log(i);
此处控制台将显示值 [0, 1, 2] 和 3。
但是如果创建一个函数,将它存储起来,稍后在使用 i 变量的 for 循环中使用。这么做可能会出现问题。 这是因为存储的函数将始终引用更新后的全局 i 变量的值。
var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
此处控制台将显示值 3而不是 2。这是因为赋值给 i 的值已经更新,printNumTwo() 返回全局的 i,而不是在 for 循环中创建函数时 i 的值。而 let 关键字就不会出现这种现象:
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
console.log(i);
在这里控制台将显示值 2 和一个错误提示 i is not defined。
改变一个用 const 声明的数组
了解使用 const 分配给变量的对象(包括数组和函数)仍然是可变的。 使用 const 声明只能防止变量标识符的重新分配。
const s = [5, 6, 7];
s = [1, 2, 3];
s[2] = 45;
console.log(s);
s = [1, 2, 3] 将导致错误。 console.log 将显示值 [5, 6, 45]。
所以说,可以改变对象 [5, 6, 7] 本身,变量 s 仍将指向更改后的数组 [5, 6, 45]。
防止对象改变
const 声明并不会真的保护数据不被改变。 为了确保数据不被改变,JavaScript 提供了一个函数 Object.freeze。
let obj = {
name:"FreeCodeCamp",
review:"Awesome"
};
Object.freeze(obj);
obj.review = "bad";
obj.newProp = "Test";
console.log(obj);
obj.review 和 obj.newProp 赋值将导致错误,控制台将显示值 { name: “FreeCodeCamp”, review: “Awesome” }。
使用箭头函数编写简洁的匿名函数
遇到不需要给函数命名的情况,尤其是在需要将一个函数作为参数传给另外一个函数的时候。 这时,我们会创建匿名函数。 因为这些函数不会在其他地方复用,所以我们不需要给它们命名。
///通常创建函数的写法//
const myFunc = function() {
const myVar = "value";
return myVar;
}
///使用箭头函数/
const myFunc = () => {
const myVar = "value";
return myVar;
}
当不需要函数体,只返回一个值的时候,箭头函数允许你省略 return 关键字和外面的大括号。 这样就可以将一个简单的函数简化成一个单行语句。
const myFunc = () => "value";
这段代码默认会返回字符串 value。
编写带参数的箭头函数
const doubler = (item) => item * 2;
doubler(4);
如果箭头函数只有一个参数,则可以省略参数外面的括号/
const doubler = item => item * 2;
可以给箭头函数传递多个参数
const multiplier = (item, multi) => item * multi;
multiplier(4, 2);
doubler(4) 将返回 8。
multiplier(4, 2) 将返回 8
设置函数的默认参数
如:
const greeting = (name = "Anonymous") => "Hello " + name;
console.log(greeting("John"));
console.log(greeting());
控制台将显示字符串 Hello John 和 Hello Anonymous。
将 rest 操作符与函数参数一起使用
function howMany(...args) {
return "You have passed " + args.length + " arguments.";
}
console.log(howMany(0, 1, 2));
console.log(howMany("string", null, [1, 2, 3], { }));
控制台将显示字符串 You have passed 3 arguments. 和 You have passed 4 arguments.。
使用 rest 参数,就不需要查看 args 数组,并且允许我们在参数数组上使用 map()、filter() 和 reduce()。
使用解构赋值来获取对象的值
const user = { name: 'John Doe', age: 34 };
//赋值/
const name = user.name;
const age = user.age;
//解构赋值语句,实现相同效果///
const { name, age } = user;
使用解构赋值从对象中分配变量
可以给解构的值赋予一个新的变量名, 通过在赋值的时候将新的变量名放在冒号后面来实现。
举例说明:
const user = { name: 'John Doe', age: 34 };
这是指定新的变量名的例子:
const { name: userName, age: userAge } = user;
可以这么理解这段代码:获取 user.name 的值,将它赋给一个新的变量 userName。
userName 的值将是字符串 John Doe,userAge 的值将是数字 34。
使用解构赋值从嵌套对象中分配变量
如:
const user = {
johnDoe: {
age: 34,
email: 'johnDoe@freeCodeCamp.com'
}
};
//这是解构对象的属性值赋值给具有相同名字的变量/
const { johnDoe: { age, email }} = user;
///这是将对象的属性值赋值给具有不同名字的变量/
const { johnDoe: { age: userAge, email: userEmail }} = user;