1.ECMAScript6

入门

在这里插入图片描述
在线文档

let和const命令

在这里插入图片描述

变量的提升问题

在这里插入图片描述

function text1(){
 console.log(name); //undefined
 console.log(age); //undefined
 var name = "zhangsan";
 var age = 20;
 console.log(name); //zhangsan
 console.log(age); //20
}
text1();
//等价于如下
function text2(){
 var name,age;
 console.log(name); //undefined
 console.log(age); //undefined
 name = "zhangsan";
 age = 20;
 console.log(name); //zhangsan
 console.log(age); //20
}
text2();
//注意:在函数内加var为局部变量,不加var则是全局变量(在执⾏当前函数之后)

let声明的变量⼀旦⽤let声明,那么在声明之前,此变量都是不可⽤的,术语称为 “暂时性死区” 。

console.log(a); //undefined
//console.log(b); //引⽤错误ReferenceError: Cannot access 'b' before
initialization
var a = 10;
let b = 20;
console.log(a); //10
console.log(b); //20

在这里插入图片描述

var tmp ="aaa";
if(true){
 // TDZ开始
 //tmp = 'bbb'; // ReferenceError
 //console.log(tmp); // ReferenceError
 let tmp; // TDZ结束
 console.log(tmp); // undefined
 tmp = "ccc";
 console.log(tmp); // ccc
}

重复声明变量

在这里插入图片描述

function demo(c){
 var a = 10;
 var a = 20; //可以使⽤var重复声明var已经声明过的变量a
 //let a = 30; //报错,不可以使⽤let声明已经被var声明过的变量a
 //错误信息:SyntaxError: Identifier 'a' has already been declared
 let b = 30;
 //let b = 40; //报错,不可以使⽤let重复声明变量b
 //var b = 50; //报错,不可以使⽤var声明已经被let声明过的变量
 //SyntaxError: Identifier 'b' has already been declared
 //let c = 70; //报错,不可以使⽤let重复声明已存在的参数c
  //SyntaxError: Identifier 'c' has already been declared
}
demo(60);

块级作⽤域

let命令所在的代码块内有效,并且所⽤域也仅限于当前代码有效

//案例1:使⽤let声明变量只在代码块中有效
{
 var a = 10;
 let b = 20; }
console.log(a); //10
//console.log(b); //报错 ReferenceError: b is not defined

//案例2: for循环的计数器,就很合适使⽤let命令。
for(var i=0;i<10;i++){}
console.log(i); //10
for(let j=0;j<10;j++){}
//console.log(j); //报错:ReferenceError: j is not defined

//案例3
var m = [];
for (var i = 0; i < 10; i++) {
 m[i] = function () {
 console.log(i);
 };
}m[6](); // 10
//数组m成员⾥⾯的i,都指向的是同⼀个i,导致运⾏时输出的是最后⼀轮的i的值,也就是 10
var n = [];
for (let i = 0; i < 10; i++) {
 n[i] = function () {
 console.log(i);
 };
}n[6](); // 6
//for循环变量的这部分是⼀个⽗作⽤域,⽽循环体内部是⼀个单独的⼦作⽤域
//⽽let,声明的变量仅在块级作⽤域内有效,最后输出的是6
/*
类似于如下格式
var aa = [];
{
 let i = 1;
 {
 let k = i
 aa[k] = function(){
 console.log(k)
 }
 }
 i++;
 {
 let k = i
 aa[k] = function(){
 console.log(k)
 }
 }
 ...
}
*/

定义常量–const命令

在这里插入图片描述

//案例1:常量不可修改,重复声明
const PI = 3.1415926;
console.log(PI)
//PI = 3.14 //常量不可再次赋值:
// 原因:TypeError: Assignment to constant variable.
//const PI = 3.14 //不可重复声明
// 原因:SyntaxError: Identifier 'PI' has already been declared

//案例2:常量声明只在块级别所⽤域内有效
{
 const CEO = "⾸席执⾏官"
 console.log(CEO) }
//console.log(CEO) //报错:ReferenceError: CEO is not defined

//案例3:常量也是不可提升,及必须在声明后使⽤常量
//console.log(CTO) //ReferenceError: Cannot access 'CTO' before initialization
const CTO = "⾸席技术官"
console.log(CTO)

在这里插入图片描述

//定义⼀个⼈这个常量对象
const person = {name:'zhangsan',age:20};
//尝试修改⼈对象,是不可以修改的。
//person = {name:"lisi",age:22}
//TypeError: Assignment to constant variable. 分配给常量变量
//但是修改person对象中的⼀个属性值,可以成功
person.age = 30;
console.log(person); //{name: "zhangsan", age: 30}
//若是连属性都不可以修改的话,可以使⽤ES5中的Object.freeze()
const p = Object.freeze(person);
p.age = 25; //没有报错,但是修改不了属性值
console.log(person); //{name: "zhangsan", age: 30}

变量的解构赋值

ES6 允许按照⼀定模式,从数组和对象中提取值,对变量进⾏赋值,这被称为 解构

数组的解构赋值

属于“模式匹配”,只要等号两边的模式相同,左边的变量就会被赋予对应的值。

//声明多个变量并赋值
let a = 10;
let b = 20;
let c = 30;
//ES6 允许写成下⾯这样
let [x,y,z]=[10,20,30];
console.log(x); //10
console.log(y); //20
console.log(z); //30
//从数组中提取值,按照对应位置,对变量赋值
let [x1,[[y1],z1]]=[10,[[20],30]]; //嵌套数组
console.log(x1); //10
console.log(y1); //20
console.log(z1); //30

其它数组的解构赋值

//解构赋部分数值
let [m, n] = [10,20,30];
console.log(m); //10
console.log(n); //20
let [i,[j],k] = [10,[20,30],40];
console.log(i); //10
console.log(j); //20
console.log(k); //40
let [x, , y] = [1, 2, 3];
console.log(x); //1
console.log(y); //3
let [ , , z] = ["one", "two", "three"];
console.log(z); //three
//其中...为ES6的扩展运算符,即d加上...可以接收多个值
let [a, ...d] = [1, 2, 3, 4];
console.log(a); // 1
console.log(d); // [2, 3, 4]
let [x1, y1, ...z1] = ['a'];
console.log(x1); // "a"
console.log(y1); // undefined
console.log(z1); // []
//没有接收到值得变量,默认为undefined
let [z2] = []; //z2:undefined
let [x2, y2] = [1]; //x2:1,y2:undefined

如果等号的右边不是数组(或者严格地说,不是可遍历的结构(Iterator)),那么将会报错。

// 以下都会报类型错误
let [foo] = 1; //TypeError: 1 is not iterable 不是可迭代的
let [foo] = false; //TypeError: false is not iterable
let [foo] = NaN;
let [foo] = undefined;
let [foo] = null;
let [foo] = {};

默认值:

//当⼀个数组成员严格等于undefined,默认值才会⽣效。
let [b = true] = [];
console.log(b); //true
let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x1, y1 = 'b'] = ['a', undefined]; // x1='a', y1='b'
console.log(x); //a
console.log(y); //b
let [m = 1] = [undefined];
console.log(m) // 1
let [n = 1] = [null]; //值不是undefined,所以没有使⽤默认值
console.log(n) // null

对象的解构赋值

解构不仅可以⽤于数组,还可以⽤于对象。

//对象的解构赋值与数组不同,要求变量必须与属性同名,才能取到正确的值。
//let {name, age} = {name:'张三', age:20};
let {age, name} = {name:'张三', age:20};
let {sex} = {name:'张三', age:20};//解构失败,变量的值等于undefined
console.log(name); //张三
console.log(age); //20
console.log(sex); //undefined
//如果变量名与属性名不⼀致,必须写成下⾯这样
let {email:em, password:ps} = {email:'zs@163.com', password:'123456'};
//如上代码email和password都是匹配的模式,em才是变量。真正被赋值的是变量em,⽽不是模式
email
console.log(em); //zs@163.com
console.log(ps); //123456
console.log(email); //错误 ReferenceError: email is not defined

与数组⼀样,解构也可以⽤于嵌套结构的对象

//定义⼀个书的信息
var obj = {
 book: [
 'JavaScript权威指南',
 {author:'⼩淘',price:132}
 ]
};
//let {book:[title, {author, price}]} = obj;
//此时book是模式,不是变量,因此不会被赋值。如果book也要作为变量赋值,可写成如下:
let {book,book:[title, {author, price}]} = obj;
console.log(title); //JavaScript权威指南
console.log(author);//⼩淘
console.log(price); //132
console.log(book); //['JavaScript权威指南',{author:'⼩淘',price:132}]

对象的解构也可以指定默认值

var {x=3} = {};
console.log(x); // 3
var {x1, y1=5} = {x1:1};
console.log(x1); // 1
console.log(y1); // 5
var {x2: y2=3} = {};
console.log(y2); // 3
var {x3: y3=3} = {x3: 5};
console.log(y3); // 5

字符串的解构赋值(了解)

字符串也可以解构赋值。这是因为此时,字符串被转换成了⼀个类似数组的对象。

const [a, b, c, d, e] = 'hello';
console.log(a); // "h"
console.log(b); // "e"
console.log(c); // "l"
console.log(d); // "l"
console.log(e); // "o"

类似数组的对象都有⼀个length属性,因此还可以对这个属性解构赋值。

let {length : len} = 'hello';
console.log(len); // 5

数值和布尔值的解构赋值(了解)

解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

//解构赋值的规则是,只要等号右边的值不是对象或数组,就先将其转为对象。
let {toString: s1} = 123;
//数值和布尔值的包装对象都有toString属性
console.log(s1 === Number.prototype.toString); // true
let {toString: s2} = true;
console.log(s2 === Boolean.prototype.toString); // true
//由于undefined和null⽆法转为对象,所以对它们进⾏解构赋值,都会报错。
let { prop: x3 } = undefined; // TypeError
let { prop: y3 } = null; // TypeError

函数参数的解构赋值

//函数的参数也可以使⽤解构赋值。
function move({x=0, y=0} = {}) {
 return [x, y];
}
console.log(move({x:3, y:8})); // [3, 8]
console.log(move({x:3})); // [3, 0]
console.log(move({})); // [0, 0]
console.log(move()); // [0, 0]

圆括号问题(了解)

在这里插入图片描述

// 变量声明语句,模式不能使⽤圆括号,以下6⾏全部报错
// let [(a)] = [1];
// let {x: (c)} = {};
// let ({x: c}) = {};
// let {(x: c)} = {};
// let {(x): c} = {};
// let { o: ({ p: p }) } = { o: { p: 2 } };
//函数参数也属于变量声明,因此也不能带有圆括号
//function f([(z)]) { return z; }
//function f([z,(x)]) { return x; }
//将整个模式放在圆括号之中,导致报错
//({ p: a }) = { p: 42 };
//([a]) = [5];
//将⼀部分模式放在圆括号之中,导致报错
// let[({ p: a }), { x: c }] = [{}, {}];
//可以使⽤圆括号的情况只有⼀种:赋值语句的⾮模式部分,可以使⽤圆括号。
let b,d;
[(b)] = [3]; // 正确 模式是取数组的第⼀个成员跟圆括号⽆关
({p:(d)} = {p:20}); // 正确 模式是p,⽽不是d
[(parseInt.prop)] = [3]; // 正确 与第⼀⾏语句的性质⼀致。
// ⾸先它们都是赋值语句,⽽不是声明语句;其次它们的圆括号都不属于模式的⼀部分

⽤途

交换变量的值

let x = 1;
let y = 2; [x, y] = [y, x];`

从函数返回多个值

// 函数只能返回⼀个值,如果要返回多个值,只能将它们放在数组或对象⾥返回。
// 有了解构赋值,取出这些值就⾮常⽅便。
// 返回⼀个数组
function example1() {
 return [1, 2, 3];
}
let [a, b, c] = example1();
// 返回⼀个对象
function example2() {
 return {
 foo: 1,
 bar: 2
 };
}
let { foo, bar } = example2();

函数参数的定义

// 解构赋值可以⽅便地将⼀组参数与变量名对应起来
// 参数是⼀组有次序的值
function f([x, y, z]) { ... }
f([1, 2, 3]);
// 参数是⼀组⽆次序的值
function f({x, y, z}) { ... }
f({z: 3, y: 2, x: 1});

提取 JSON 数据

// 解构赋值对提取 JSON 对象中的数据,尤其有⽤。
let jsonData = {
 id: 42,
 status: "OK",
 data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]

函数的扩展

函数参数的默认值

在这里插入图片描述

//ES6之前,不能直接为函数的参数指定默认值,只能采⽤变通的⽅法。
function func(name){
 name = name || "World";
 return "Hello "+name; }
console.log(func()); //Hello World
console.log(func("ZhangSan")); //Hello ZhangSan
//ES6允许为函数的参数设置默认值,即直接写在参数定义的后⾯。
function add(x=0,y=0){
 return x+y; }
console.log(add()); //0
console.log(add(10)); //10
//跳过第⼀个参数给第⼆个参数y传值
console.log(add(undefined,20)); //20
console.log(add(10,20));//30

箭头函数

ES6允许使⽤“箭头”(=>)定义函数。

var f = v => v;
// 等同于
var f = function (v) {
 return v;
};

如果箭头函数不需要参数或需要多个参数,就使⽤⼀个圆括号代表参数部分

//⽆参数
var f = () => 5;
// 等同于
var f = function () { return 5 };
//多个参数
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
 return num1 + num2;
};

如果箭头函数的代码块部分多于⼀条语句,就要使⽤⼤括号将它们括起来,并且使⽤return语句返
回。

var sum = (num1, num2) => { return num1 + num2; }

由于⼤括号被解释为代码块,所以如果箭头函数直接返回⼀个对象,必须在对象外⾯加上括号,否
则会报错。

// 报错
let getTempItem = id => { id: id, name: "Temp" };
// 不报错
let getTempItem = id => ({ id: id, name: "Temp" });

箭头函数中this的理解

传统javaScript代码中this的使⽤

//定义⼀个stu学⽣对象,内有:两个属性、⼀个⽅法。
const stu = {
 name:"张三",
 likes:['吃饭','睡觉','敲代码'],
 printLikes:function(){
 //使⽤map遍历likes属性,并输出信息
 this.likes.map(function(like){
 //此处的this代表的是window对象,⽽⾮stu对象
 console.log(`${this.name} 喜欢 ${like}`);
 });
 }
};
stu.printLikes(); //使⽤stu对象调⽤⾃⼰的⽅法
/* 输出结果:
 喜欢 吃饭
 喜欢 睡觉
 喜欢 敲代码
*/

上⾯的输出this.name没有信息,如下进⾏修改就可以了

//定义⼀个stu学⽣对象,内有:两个属性、⼀个⽅法。
const stu = {
 name:"张三",
 likes:['吃饭','睡觉','敲代码'],
 printLikes:function(){
 let self = this;
 //使⽤map遍历likes属性,并输出信息
 this.likes.map(function(like){
 //此处的this代表的是window对象,⽽⾮stu对象
 console.log(`${self.name} 喜欢 ${like}`);
 });
 }
};
stu.printLikes(); //使⽤stu对象调⽤⾃⼰的⽅法
/* 输出结果:
 张三 喜欢 吃饭
 张三 喜欢 睡觉
 张三 喜欢 敲代码
*/

使⽤箭头函数后的效果

//定义⼀个stu学⽣对象,内有:两个属性、⼀个⽅法。
const stu = {
 name:"张三",
 likes:['吃饭','睡觉','敲代码'],
 printLikes:function(){
 //使⽤map遍历likes属性,并输出信息
 this.likes.map(like => {
 //箭头函数中没有⾃⼰的this,故此处this是继承⽗作⽤域的。
 //⽽且是在定义的时候已指定,不会随着调⽤⽽改变。
 console.log(`${this.name} 喜欢 ${like}`);
 });
 }
 };
stu.printLikes(); //使⽤stu对象调⽤⾃⼰的⽅法
/* 输出结果:
 张三 喜欢 吃饭
 张三 喜欢 睡觉
 张三 喜欢 敲代码
*/

箭头函数使⽤注意点在这里插入图片描述

//1.箭头函数不可以作为构造函数使⽤
const Stu1 = (name,age)=>{
 this.name = name;
 this.age = age; }
//要改成常规函数如下:
const Stu2 = function(name,age){
 this.name = name;
 this.age = age; }
//实例化
//s = new Stu1("zhangsan",20);//报错:TypeError: Stu is not a constructor
s = new Stu2("zhangsan",20); //正常
console.log(s); //Stu2 {name: "zhangsan", age: 20}

//定义Stu类
const Stu = function(name,age){
 this.name = name;
 this.age = age; }s = new Stu("zhangsan",20); //正常实例化
//为s原型对象添加⼀个getInfo⽅法,使⽤箭头函数,⾥⾯的this是window对象
Stu.prototype.getInfo = ()=>{
 return `我叫${this.name},今年${this.age}岁`; }
//改成常规函数
Stu.prototype.getInfo2 = function(){
 return `我叫${this.name},今年${this.age}岁`; }
console.log(s.getInfo()); //我叫,今年undefined岁
console.log(s.getInfo2()); //我叫zhangsan,今年20岁

数组的扩展

数组的遍历

//定义数组
let a = ["aaa","bbb","ccc"];
a.name = "zhangsan"; //添加⾮数字属性
//1.使⽤for循环遍历数组(传统⽅式)
for(let i=0;i<a.length;i++){
 console.log(a[i]);
}
//2.使⽤for...in遍历(特点是会遍历出其他⾮数字属性信息)
for(let i in a){
 console.log(a[i])
}
//3.使⽤forEach遍历数组(不⽀持break和continue) a.forEach(function(v){
 console.log(v);
});
//使⽤箭头函数
a.forEach(v =>{
 console.log(v);
});
//4.ES6我们提供了for...of循环
//特点不会遍历⾮数字属性,⽀持break和continue的使⽤
for(let v of a){
 console.log(v) }

** for…of循环的使⽤实例**
在这里插入图片描述

//数组对象entries()⽅法返回⼀个数组的迭代对象,该对象包含数组的键值对(key/value)。
//1.使⽤for...of遍历数组:
let a = ['zhangsan','lisi','wangwu'];
for(let [k,v] of a.entries()){
 console.log(k,v);
}
//0 "zhangsan"
//1 "lisi"
//1 "lisi"
//2.使⽤for...of遍历Maps(映射)
const iterable1 = new Map([['one','zhangsan'],['two','lisi'],
['three','wangwu']]);
for (const [key, value] of iterable1) {
 console.log(`${key} -> ${value}`);
}
//one -> zhangsan
//two -> lisi
//three -> wangwu
//Set(集合) 对象允许你存储任何类型的唯⼀值,这些值可以是原始值或对象。
//3.使⽤for...of遍历Set(集合)
const iterable2 = new Set([10,30,20,10,30]);
for (const value of iterable2) {
 console.log(value);
}
//10
//30
//20
//字符串⽤于以⽂本形式存储数据
//4.使⽤for...of遍历字符串
const iterable3 = 'Hello';
for (const value of iterable3) {
 console.log(value);
}
//H
//e
//l
//l
//o
//5.使⽤for...of遍历arguments Object(参数对象)
function demo(){
 for(const arg of arguments) {
 }
}
demo('a','b','c');
//a
//b
//c

Array.from()
在这里插入图片描述

let array = {
 0: 'name',
 1: 'age',
 2: 'sex',
 3: ['user1','user2','user3'],
 'length': 4
};
let arr = Array.from(array);
console.log(arr); // ['name','age','sex',['user1','user2','user3']]

Array.from()的案例

<!DOCTYPE html>
<html lang="en"> <head>
 <meta charset="UTF-8">
 <title>Array.from()使⽤实例</title>
</head> <body>
 <ul>
 <li>zhangsan</li>
 <li>lisi</li>
 <li>wangwu</li>
 </ul>
 <script type="text/javascript">
 //获取上⾯的li节点对象列表
 let nlists = document.querySelectorAll("li");
 console.log(nlists); //NodeList(3) [li, li, li]
 //将NodeList列表对象转成数组,并解析出每个元素之间的内容。
 const alist = Array.from(nlists,li => li.textContent);
 console.log(alist); // ["zhangsan", "lisi", "wangwu"]
 </script>
</body>
</html>

** Array.of()**
Array.of()⽅法⽤于将⼀组值转化为数组,即新建数组,⽽不考虑参数的数量或类型。

//使⽤Array.of()创建数组
console.log(Array.of()); //[] 创建⼀个空数组
console.log(Array.of(8)); //[8] 创建只有⼀个元素值为8的数组
console.log(Array.of(1, 2, 3)); //[1,2,3] 创建⼀个值为1,2,3的数组
//以前直接使⽤Array创建数组
console.log(Array()); //[] 创建⼀个空数组
console.log(Array(4)); // [ , , , ] 创建拥有4个元素空值的数组
console.log(Array(1, 2, 3)); //[1,2,3] 创建⼀个值为1,2,3的数组

数组实例的 find() 和 findIndex()在这里插入图片描述

const data =[
 {name:'zhangsan',age:22,sex:'man'},
 {name:'lisi',age:25,sex:'woman'},
 {name:'wangwu',age:23,sex:'man'},
];
//使⽤find获取name属性值为lisi的信息
let s1 = data.find(function(v){
 return v['name']=='lisi'
});
//同上效果使⽤箭头函数
let s2 = data.find(v => v['name']=='lisi');
console.log(s1); //{name: "lisi", age: 25, sex: "woman"}
console.log(s2); //{name: "lisi", age: 25, sex: "woman"}
//使⽤find获取name属性值为lisi的信息
let s3 = data.findIndex(function(v){
 return v['name']=='lisi'
});
//同上效果使⽤箭头函数
let s4 = data.findIndex(v => v['name']=='lisi');
console.log(s3); //1
console.log(s4); //1

数组实例的 some() 和 every()
在这里插入图片描述

const data =[
 {name:'zhangsan',age:22,sex:'man'},
 {name:'lisi',age:25,sex:'woman'},
 {name:'wangwu',age:23,sex:'man'},
];
//使⽤some判断data中是否含有⼀条name以"wang"开头的
let s1 = data.some(v => v['name'].startsWith("wang"));
console.log(s1); //true
//使⽤every判断data信息中是否都是age⼤于20的信息。
let s2 = data.every(v => v['age']>20);
console.log(s2); //true 若有⼀个不符合则返回false

数组实例的 .fill()
在这里插入图片描述

//空数组则没有替换
console.log([].fill(6)); //[]
//将数组中的值都替换成指定值6
console.log([1,2,3].fill(6));//(3) [6, 6, 6]
//从数组索引位置2开始替换成指定值6,替换到数组结束位置。
console.log([1,2,3,4,5].fill(6,2)); //(5) [1, 2, 6, 6, 6]
//从数组索引位置2开始替换到索引位置4前结束。
console.log([1,2,3,4,5].fill(6,2,4)); //(5) [1, 2, 6, 6, 5]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值