javaScript高级[三]
ES6新增语法
let
ES6中新增的用于声明变量的关键字。
- let声明的变量只在所处于的块级有效
if(true){
let a = 10;
}
console.log(a) // a is not defined
注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。
<script type="text/javascript">
/* --------let关键字就是用来声明变量的-------- */
// let a = 10;
// console.log(a);// 10
/* --------使用let关键字声明的变量具有块级作用域-------- */
// if (true) {
// let b = 20;
// console.log(b);//20
// if (true) {
// let c = 30;
// }
// console.log(c);//报错
// }
// console.log(b)
/* -------在一个大括号中 使用let关键字声明的变量才具有块级作用域 var关键字是不具备这个特点的--------- */
// if (true) {
// let num = 100;
// var abc = 200;
// }
// console.log(abc); // 200
// console.log(num); // 报错
/* -------防止循环变量变成全局变量--------- */
for (let i = 0; i < 2; i++) {}
console.log(i); // 报错
</script>
- 不存在变量提升
/*-----使用let关键字声明的变量没有变量提升------*/
console.log(a); // 报错 必须先声明再使用
let a = 100;
- 暂时性死区
在块级作用域内声明的变量,就和这个块级作用域整体进行了绑定,不会受到外部影响
/* -------使用let关键字声明的变量具有暂时性死区特性------- */
var num = 10
if (true) {
console.log(num); // 报错 因为{}内外的num毫无关系,这里在{}内先使用后定义就会报错;
// {}内的num不会向上一级作用域查找num
let num = 20;
}
const
作用:声明常量,常量就是值(内存地址)不能变化的量。
- 具有块级作用域
if (true) {
const a = 10;
console. log (a) // a is not defined
}
- 声明常量时必须赋值
const PI; // Missing initializer in const declaration
- 常量赋值后,值不能修改。
const PI = 3.14;
PI = 100; // Assignment to constant variable.
const ary = [100,200];
ary[0] = 'a';
ary[1]='b';
console.log(ary); // ['a', 'b'];
ary = ['a', 'b'];// Assignment to constant variable.
在用const赋值之后:
- 对于基本数据类型,一旦赋值,值不可更改,指的就是值对应的内存地址不可更改
- 不可以重新赋值,但是可以更改数据结构内部的值
<script type="text/javascript">
// 1. 使用const关键字声明的常量具有块级作用域
// if (true) {
// const a = 10;
// if (true) {
// const a = 20;
// console.log(a);//20
// }
// console.log(a);//10
// }
// console.log(a);//报错
// 2. 使用const关键字声明的常量必须赋初始值
// const PI;//报错
// 3. 常量声明后值不可更改
const PI = 3.14;
// PI = 100;//报错
const ary = [100, 200];
ary[0] = 123; //不报错 ary在内存中的地址没变
ary = [1, 2] //报错 因为改变了ary在内存中的存储地址
console.log(ary);
</script>
var let const的区别
- 使用var声明的变量,其作用域为该语句所在的函数内,且存在变量提升现象
- 使用let声明的变量,其作用域为该语句所在的代码块内,不存在变量提升。
- 使用const声明的是常量,在后面出现的代码中不能再修改该常量的值。
var | let | const |
---|---|---|
函数级作用域 | 块级作用域 | 块级作用域 |
变量提升 | 不存在变量提升 | 不存在变量提升 |
值可更改 | 值可更改 | 值不可更改 |
解构赋值
分解数据结构,为变量赋值
数组解构
let [a, b,c]=[1,2,3];
console.log (a)
console.log(b)
console.log(c)
如果解构不成功,变量的值为undefined。
let [foo] = [];
let [bar,foo] = [1];
<script type="text/javascript">
// 数组解构允许我们按照一一对应的关系从数组中提取值 然后将值赋值给变量
let ary = [1, 2, 3];
// 曾经获取数组内部的值 要声明3次变量
// var a = ary[0]
// var b = ary[1]
// var c = ary[2]
let [a, b, c, d, e] = ary; // abcde都是变量
console.log(a) // 1
console.log(b) // 2
console.log(c) // 3
console.log(d) // undefined
console.log(e) // undefined
</script>
对象解构
实质是属性匹配,变量的名字匹配对象中属性的名字
<script type="text/javascript">
// 对象解构允许我们使用变量的名字匹配对象的属性 匹配成功 将对象属性的值赋值给变量
let person = {
name: '李四',
age: 30,
sex: '男'
};
let {name, age, sex} = person;// name, age, sex都是变量,和属性名必须相同
console.log(name)// 李四
console.log(age)// 30
console.log(sex)// 男
</script>
对象解构的另一种写法
<script type="text/javascript">
// 对象解构允许我们使用变量的名字匹配对象的属性 匹配成功 将对象属性的值赋值给变量
let person = {
name: 'lisi',
age: 30,
sex: '男'
};
let {name: myName} = person;// myName才是真正的变量,name仅仅用于属性匹配
console.log(name)// 空
console.log(myName)// lisi
</script>
箭头函数
ES6中新增的定义函数的方式
()=>{}
const fn = ()=>{}
- (形参) {函数体}
- 通过fn调用函数
// 箭头函数是用来简化函数定义语法的
const fn = () => {
console.log(123)
}
fn();// 123
- 函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
function sum (num1, num2){
return num1 + num2;
}
const sum = (num1 , num2) => num1 + num2;
上图是过去和现在两种定义函数方法的比较
// 在箭头函数中 如果函数体中只有一句代码 并且代码的执行结果就是函数的返回值 函数体大括号可以省略
// const sum = (n1, n2) => {
// return n1 + n2;
// };
// 等效于
const sum = (n1, n2) => n1 + n2;
// 调用函数
const result = sum(10, 20);
console.log(result) // 30
- 如果形参只有一个,可以省略小括号
function fn (v) {
return v;
}
const fn = v =>v;
// 在箭头函数中 如果形参只有一个 形参外侧的小括号也是可以省略的
const fn = v => {
alert(v);
}
fn(20)
- 箭头函数不绑定this关键字,箭头函数中的this,指向的是函数定义位置的上下文this。
// 箭头函数不绑定this 箭头函数没有自己的this关键字 如果在箭头函数中使用this this关键字将指向箭头函数定义位置中的this
function fn() {
console.log(this); //{name: 'zhangsan'}
return () => {
console.log(this) //{name: 'zhangsan'}
}
}
const obj = {
name: 'zhangsan'
};
const resFn = fn.call(obj); //fn.call(obj)将fn函数内部的this指向obj对象
resFn(); //{name: 'zhangsan'}
经典面试题
var obj = {
age: 20,
say: () => { // obj是一个对象被,不能产生作用域,所以这个函数实际上是被定义在全局作用域中
alert(this.age) // this指向window ,window中没有age属性
}
}
obj.say();// 弹出undefined
var age = 100;
var obj = {
age: 20,
say: () => { // obj是一个对象被,不能产生作用域,所以这个函数实际上是被定义在全局作用域中
alert(this.age) // this指向window ,window中没有age属性
}
}
obj.say(); //100
剩余参数
- 当函数实参个数大于形参个数时,可以将剩余的实参放到一个数组中
- 剩余参数语法允许我们将一个不定数量的参数表示为一个数组。
<script>
// ES6之前通常使用argument,但是在箭头函数中使用不了argument
// 一下是报错写法:argument.forEach is not a function
// function sum(argument) {
// let total = 0;
// argument.forEach(function(item) {
// total = total + item;
// });
// return total;
// }
// 正确写法1
// function sum(first, ...args) {
// let total = 0;
// args.forEach(function(item) {
// total = total + item;
// });
// return total;
// }
// 正确写法2
// const sum = (first, ...args) => {
// let total = 0;
// args.forEach(function(item) {
// total = total + item;
// });
// return total;
// }
//正确写法3
// const sum = (first, ...args) => {
// let total = 0;
// args.forEach((item) => {
// total = total + item;
// });
// return total;
// };
//正确写法4
const sum = (first, ...args) => {
let total = 0;
args.forEach((item) => total += item);
return total;
}
console.log(sum(10, 20)); //20
console.log(sum(10, 20, 30)); //50
</script>
- 注:参数名…args可以任意更替为…a…b…c等其他变量名
- 剩余参数和解构配合使用
let students = ['wangwu', 'zhangsan', 'lisi'];
let [s1, ...s2] = students;
console.log(s1); // 'wangwu'
console.log(s2); // ['zhangsan', 'lisi']
// 剩余参数和结构配合使用
let ary1 = ['张三', '李四', '王五'];
let [s1, ...s2] = ary1;
console.log(s1);// 张三
console.log(s2);//(2) ["李四", "王五"]
ES6之Array扩展方法
扩展运算符(展开语法)
扩展运算符可以将数组或者对象转为用逗号分隔的参数序列
let ary = [1,2,3];
...ary // 1,2,3
console.log (...ary); // 1 2 3
上述输出结果中没有逗号的原因:
- 逗号被当作是console.log()方法的参数分隔符了
扩展运算符和剩余参数正好相反
- 剩余参数:将剩余的元素放在一个数组中;
- 扩展运算符:可以将数组或者对象转为用逗号分割的参数序列;
// 扩展运算符可以将数组拆分成以逗号分隔的参数序列
let ary = ["a", "b", "c"];
// ...ary // "a", "b", "c"
console.log(...ary); //a b c
// 相当于
console.log("a", "b", "c"); // a b c
扩展运算符可以应用于合并数组
// 方法一
let ary1 = [1,2,3];
let ary2 = [3,4,5] ;
let ary3 = [...ary1, ...ary2];
console.log(ary3); // (6) [1, 2, 3, 4, 5, 6]
// 方法二
let ary4 = [7, 8, 9];
ary1.push(...ary2, ...ary4);
console.log(ary1); // (9) [1, 2, 3, 4, 5, 6, 7, 8, 9]
将类数组或可遍历对象转换为真正的数组
let oDivs = document.getElementsByTagName ('div') ;
oDivs = [...oDivs] ;
// 利用扩展运算符将伪数组转换为真正的数组
var oDivs = document.getElementsByTagName('div');
console.log(oDivs); // HTMLCollection (6) [div, div, div, div, div, div] 这是一个伪数组
// ...oDivs // 将伪数组转换为逗号分割的参数序列
var ary = [...oDivs]; //变成真正的数组
// 将伪数组转换为真正的数组之后,就可以调用数组对象中的真正的方法
ary.push('a');
console.log(ary); // (7) [div, div, div, div, div, div, "a"]
构造函数方法
Array.from()方法
- Array.from()以伪数组作为第一个参数,返回值是一个真正的数组
var arrayLike = { // 这是一个伪数组
"0": "张三",
"1": "李四",
"2": "王五",
"length": 3
}
var ary = Array.from(arrayLike); // ary是一个真正的数组
console.log(ary)
- 方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
var arrayLike = {
"0": "1",
"1": "2",
"length": 2
}
var ary = Array.from(arrayLike, item => item * 2)
console.log(ary); // (2) [2, 4]
- Array.from()以函数作为第二个参数,对数组中的元素进行加工处理,数组中有多少个元素函数就会被调用多少次
- 函数有一个形参,代表要处理的那个值,只需要将处理的结果返回即可
实例方法
find()方法
- 用于找出第一个符合条件的数组成员,如果没有找到返回undefined
var ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}];
let target = ary.find((item, index) => {// item是数组中的元素;index是数组的索引号
console.log(index);
return item.id == 1;
});
console.log(target);
// 0 说明查找符合条件的值就立马返回,不会继续循环
// {id: 1, name: "张三"}
- find()接收一个函数作为参数,这个参数中的函数返回的是bool值,实际上就是查找的条件
findIndex()方法
- 用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [10, 20, 50];
let index = ary.findIndex((item, index) => {
console.log(index);
return item > 15;
// console.log(index); 写在return后面则一次都不打印
});
console.log('符合条件的索引是' + index);
// 打印结果
// 0
// 1
// 符合条件的索引是1
includes()方法
- 表示某个数组是否包含给定的值,返回布尔值
let ary = ["a", "b", "c"];
let result = ary.includes('a') // true
console.log(result)
result = ary.includes('e') // false
console.log(result)
ES6之String扩展方法
模板字符串
ES6新增的创建字符串的方式,使用反引号定义。
let name = `zhangsan`;
let name = `这是一个模板字符串`;
console.log(name); // 这是一个模板字符串
模板字符串中可以解析变量
let name = `张三`;
// let sayHello = 'Hello, 我的名字叫' + name;
// 等效于
// let sayHello = `Hello, 我的名字叫` + name;
// 等效于
let sayHello = `Hello, 我的名字叫${name}`; // Hello, 我的名字叫张三
console.log(sayHello);
模板字符串中可以换行
let result = {
name: 'zhangsan',
age: 20,
sex:'男'
}
let html = `<div>
<span>${result.name}</span>
<span>${result.age}</span>
<span>${result.sex}</span>
</div>`;
console.log(html);
/*打印内容:
<div>
<span>zhangsan</span>
<span>20</span>
<span>男</span>
</div>
*/
在模板字符串中可以调用函数
const fn = () => {
return '我是fn函数'
}
let html = `我是模板字符串 ${fn()}`;
console.log(html) // 我是模板字符串 我是fn函数
startsWith()和endsWith()方法
startsWith():表示参数字符串是否在原字符串的头部,返回布尔值endsWith():表示参数字符串是否在原字符串的尾部,返回布尔值
let str ='Hello world! ';
str.startswith ( ' Hello') // true
str.endswith ( ' ! ') // true
let str = 'Hello ECMAScript 2015';
let r1 = str.startsWith('Hello');
console.log(r1); //true
let r2 = str.endsWith('2016');
console.log(r2); //false
repeat()方法
repeat方法表示将原字符串重复n次,返回一个新字符串。
let str = 'y';
let newstr = str.repeat(5);
console.log(str); // y
console.log(newstr); // yyyyy
// 或
console.log("y".repeat(5)); // yyyyy
ES6之set数据结构
Set数据结构
- ES6提供了新的数据结构Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
const s = new Set ();
Set函数可以接受一个数组作为参数,用来初始化。
const set =new Set([1,2,3,4,4]);
// 创建size数据结构的方法
const s1 = new Set();
console.log(s1.size); // 0
const s2 = new Set(["a", "b"]);
console.log(s2.size); // 2
Set数据结构还可以实现数组去重:
const s3 = new Set(["a", "a", "b", "b"]);
console.log(s3.size); // 2
const ary = [...s3];
console.log(ary); // (2) ["a", "b"]
实例方法
add(value):添加某个值,返回Set结构本身
delete(value):删除某个值,返回一个布尔值,表示删除是否成功has(value):返回一个布尔值,表示该值是否为Set的成员
clear():清除所有成员,没有返回值
const s = new set () ;
s. add(1).add(2).add (3) ; // 向set结构中添加值
s.delete(2); // 删除set结构中的2值
s.has (1); // 表示 set结构中是否有1这个值返回布尔值
s.clear (); // 清除set结构中的所有值
const s4 = new Set();
// 向set结构中添加值 使用add方法
s4.add('a').add('b');
console.log(s4.size) // 2
// 从set结构中删除值 用到的方法是delete
const r1 = s4.delete('c');
console.log(s4.size) // 2
console.log(r1); // false 删除失败
// 判断某一个值是否是set数据结构中的成员 使用has
const r2 = s4.has('d');
console.log(r2) // false
// 清空set数据结构中的值 使用clear方法
s4.clear();
console.log(s4.size); // 0
遍历
- Set结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值。
s.forEach (value =>console.log (value))
// 遍历set数据结构 从中取值
const s5 = new Set(['a', 'b', 'c']);
s5.forEach(value => {
console.log(value)
});
/*d打印输出
a
b
c
*/