比较 var 和 let 关键字的作用域
使用 var 关键字声明变量时,它是全局声明的,如果在函数内部声明则是局部声明的。
let 关键字的行为类似,但有一些额外的功能。 在代码块、语句或表达式中使用 let 关键字声明变量时,其作用域仅限于该代码块、语句或表达式
var numArray = [];
for (var i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
console.log(i);
此处控制台将显示值 [0, 1, 2] 和 3。
使用 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。
改变一个用 const 声明的数组
默认情况下,一些开发人员更喜欢使用 const 分配所有变量,除非他们知道需要重新分配值。 只有在这种情况下,他们才使用 let。
要了解使用 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]。 s 中的数组元素是可变的,但是因为使用了 const,所以不能使变量标识符 s 来指向一个使用赋值运算符的不同数组。
防止对象改变
const 声明并不会真的保护数据不被改变。 为了确保数据不被改变,JavaScript 提供了一个函数 Object.freeze。任何更改对象的尝试都将被拒绝,如果脚本在严格模式下运行,将抛出错误
使用箭头函数编写简洁的匿名函数
在 JavaScript 里,我们会经常遇到不需要给函数命名的情况,尤其是在需要将一个函数作为参数传给另外一个函数的时候。 这时,我们会创建匿名函数。 因为这些函数不会在其他地方复用,所以我们不需要给它们命名。
const myFunc = function() {
const myVar = "value";
return myVar;
}
ES6 提供了其他写匿名函数的方式的语法糖。 你可以使用箭头函数:
const myFunc = () => {
const myVar = "value";
return myVar;
}
当不需要函数体,只返回一个值的时候,箭头函数允许你省略 return 关键字和外面的大括号。 这样就可以将一个简单的函数简化成一个单行语句。
const myFunc = () => "value";
编写带参数的箭头函数
给箭头函数传参数
const doubler = (item) => item * 2;
doubler(4);
如果箭头函数只有一个参数,则可以省略参数外面的括号。
const doubler = item => item * 2;
可以给箭头函数传递多个参数。
const multiplier = (item, multi) => item * multi;
multiplier(4, 2);
给函数传入默认参数,来构建更加灵活的函数。
const greeting = (name = "Anonymous") => "Hello " + name;
将 rest 操作符与函数参数一起使用
ES6 推出了用于函数参数的 rest 操作符帮助我们创建更加灵活的函数。 rest 操作符可以用于创建有一个变量来接受多个参数的函数。 这些参数被储存在一个可以在函数内部读取的数组中。
使用 spread 运算符展开数组项
ES6 引入了展开操作符,可以展开数组以及需要多个参数或元素的表达式。
下面的 ES5 代码使用了 apply() 来计算数组的最大值:
var arr = [6, 89, 3, 45];
var maximus = Math.max.apply(null, arr);
maximus 的值为 89。
我们必须使用 Math.max.apply(null, arr),因为 Math.max(arr) 返回 NaN。 Math.max() 函数中需要传入的是一系列由逗号分隔的参数,而不是一个数组。 展开操作符可以提升代码的可读性,使代码易于维护。
const arr = [6, 89, 3, 45];
const maximus = Math.max(...arr);
maximus 的值应该是 89。
…arr 返回一个解压的数组。 也就是说,它展开数组。 然而,展开操作符只能够在函数的参数中或者数组中使用。 下面的代码将会报错:
const spreaded = ...arr;
使用解构赋值来获取对象的值
解构赋值是 ES6 引入的新语法,用来从数组和对象中提取值,并优雅地对变量进行赋值。
const user = {
name: 'John Doe', age: 34 };
const name = user.name;
const age = user.age;
下面是使用 ES6 解构赋值语句,实现相同效果:
const {
name, age } = user;
在这里,自动创建 name 和 age 变量,并将 user 对象相应属性的值赋值给它们。 这个方法简洁多了。
你可以从对象中提取尽可能多或很少的值。
可以给解构的值赋予一个新的变量名, 通过在赋值的时候将新的变量名放在冒号后面来实现。
这是指定新的变量名的例子:
const {
name: userName, age: userAge } = user;
这是解构对象的属性值赋值给具有相同名字的变量:
const {
johnDoe: {
age, email }} = user;
这是将对象的属性值赋值给具有不同名字的变量:
const {
johnDoe: {
age: userAge, email: userEmail }} = user;
在解构数组的某些情况下,我们可能希望将剩下的元素放进另一个数组里面。
以下代码的结果与使用 Array.prototype.slice() 类似:
const [a, b, ...arr] = [1, 2, 3, 4, 5, 7];
console.log(a, b);
console.log(arr);
使用 class 语法定义构造函数
ES6 提供了一个新的创建对象的语法,使用关键字 class。
值得注意的是,class 只是一个语法糖,它并不像 Java、Python 或者 Ruby 这一类的语言一样,严格履行了面向对象的开发规范。
在 ES5 里面,我们通常会定义一个函数 constructor,然后使用 new 关键字来实例化一个对象。
在 ES6 里,class 声明有一个 constructor 方法,与 new 关键字一起被调用。 如果 constructor 方法没有明确定义,那么它就被含蓄地定义为没有参数。
// Explicit constructor
class SpaceShuttle {
constructor(targetPlanet) {
this.targetPlanet = targetPlanet;
}
takeOff() {
console.log("To " + this.targetPlanet + "!");
}
}
// Implicit constructor
class Rocket {
launch() {
console.log("To the moon!");
}
}
const zeus = new SpaceShuttle('Jupiter');
// prints To Jupiter! in console
zeus.takeOff();
const atlas = new Rocket();
// prints To the moon! in console
atlas.launch();
应该注意 class 关键字声明了一个新的函数,里面添加了一个构造函数。 当用 new 创建一个新的对象时,构造函数会被调用。
**注意:**首字母大写驼峰命名法 UpperCamelCase 是 ES6 class 命名的惯例,就像上面的 SpaceShuttle。
constructor 方法是一个特殊方法,用于创建和初始化 class 创建的对象。 在 JavaScript 算法和数据结构认证的面向对象编程章节里会更深入介绍它。
使用 getter 和 setter 来控制对象的访问
可以从对象中获得一个值,也可以给对象的属性赋值。
这些操作通常被称为 getters 以及 setters。
Getter 函数的作用是可以让对象返回一个私有变量,而不需要直接去访问私有变量。
Setter 函数的作用是可以基于传进的参数来修改对象中私有变量。 这些修改可以是计算,或者是直接替换之前的值。
class Book {
constructor(author) {
this._author = author;
}
// getter
get writer() {
return this._author;
}
// setter
set writer(updatedAuthor) {
this._author = updatedAuthor;
}
}
const novel = new Book('anonymous');
console.log(novel.writer);
novel.writer = 'newAuthor';
console.log(novel.writer);
请注意用于调用 getter 和 setter 的语法。 它们甚至看起来不像是函数。 getter 和 setter 非常重要,因为它们隐藏了内部的实现细节。
注意: 通常会在私有变量前添加下划线(_)。 然而,这种做法本身并不是将变量变成私有的。
用 export 来重用代码块
假设有一个文件 math_functions.js,该文件包含了数学运算相关的一些函数。 其中一个存储在变量 add 里,该函数接受两个数字作为参数返回它们的和。 你想在几个不同的 JavaScript 文件中使用这个函数。 要实现这个目的,就需要 export 它。
export const add = (x, y) => {
return x + y;
}
上面是导出单个函数常用方法,还可以这样导出:
const add = (x, y) => {
return x + y;
}
export {
add };
导出变量和函数后,就可以在其它文件里导入使用从而避免了代码冗余。 重复第一个例子的代码可以导出多个对象或函数,在第二个例子里面的导出语句中添加更多值也可以导出多项,例子如下:
export {
add, subtract };
还需要了解另外一种被称为默认导出的 export 的语法。 在文件中只有一个值需要导出的时候,通常会使用这种语法。 它也常常用于给文件或者模块创建返回值。
下面是使用 export default 的例子:
export default function add(x, y) {
return x + y;
}
export default function(x, y) {
return x + y;
}
第一个是命名函数,第二个是匿名函数。
export default 用于为模块或文件声明一个返回值,在每个文件或者模块中应当只默认导出一个值。 此外,你不能将 export default 与 var、let 或 const 同时使用。
创建一个 JavaScript Promise
Promise 是异步编程的一种解决方案 - 它在未来的某时会生成一个值。 任务完成,分执行成功和执行失败两种情况。 Promise 是构造器函数,需要通过 new 关键字来创建。 构造器参数是一个函数,该函数有两个参数 - resolve 和 reject。 通过它们来判断 promise 的执行结果。 用法如下:
const myPromise = new Promise((resolve, reject) => {
});
Promise 有三个状态:pending、fulfilled 和 rejected。 上一个挑战里创建的 promise 一直阻塞在 pending 状态里,因为没有调用 promise 的完成方法。 Promise 提供的 resolve 和 reject 参数就是用来结束 promise 的。 Promise 成功时调用 resolve,promise 执行失败时调用 reject, 如下文所述,这些方法需要有一个参数。
const myPromise = new Promise((resolve, reject) => {
if(condition here) {
resolve("Promise was fulfilled");
} else {
reject("Promise was rejected");
}
});
上面的示例使用字符串作为这些函数的参数,但参数实际上可以是任何格式。 通常,它可能是一个包含数据的对象,你可以将它放在网站或其他地方。
用 then 处理 Promise 完成的情况
当程序需要花费未知的时间才能完成时(比如一些异步操作),一般是服务器请求,promise 很有用。 服务器请求会花费一些时间,当结束时,需要根据服务器的响应执行一些操作。 这可以用 then 方法来实现, 当 promise 完成 resolve 时会触发 then 方法。 例子如下:
myPromise.then(result => {
});
使用 catch 处理 Promise 失败的情况
当 promise 失败时会调用 catch 方法。 当 promise 的 reject 方法执行时会直接调用。 用法如下:
myPromise.catch(error => {
});
error 是传入 reject 方法的参数。
result 即传入 resolve 方法的参数。
转载:https://blog.csdn.net/weixin_53333752/article/details/128760480