目录
一、var、let、const
1、let
* 1、没有变量提升,先定义后执行
* 2、let定义的变量,在一个作用域内只能被声明一次
* 3、块级作用域。let声明变量,作用域为一对{}范围内,有一层{}就有一个作用域
* 常见的带有一对{}的场景:循环语句、分支语句、函数
* 4、let关键字与函数嵌套使用,会形成闭包环境
代码实例:
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)//0 1 2 3 4
}, 3000)
}
function fn(){
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)//55555
}, 3000)
}
}
fn()
for (let i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)//0 1 2 3 4
}, 3000)
}
function fn(){
for (var i = 0; i < 5; i++) {
setTimeout(function() {
console.log(i)//55555
}, 3000)
}
}
fn()
2、const
- 用来定义常量(只能初始化一次,在程序当中不可被赋值,只读状态)程序运行期间不会改变的常量用const
const PI = 3.1415926535;
// PI = 100; //报错Assignment to constant variable
console.log(PI);
const fn = function () {
console.log(111);
};
//fn = 200;//报错Assignment to constant variable
3、var、let和const区别
1. var定义的变量,**没有块的概念,可以跨块访问**, 不能跨函数访问。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const用来定义常量,使用时`必须初始化`(即必须赋值),只能在块作用域里访问,且不能修改。
2. var可`先使用,后声明`,因为存在变量提升;`let必须先声明后使用`。
3. var是允许在相同作用域内`重复声明同一个变量`的,而let与const不允许这一现象。
4. 在全局上下文中,基于let声明的全局变量和全局对象window没有任何关系 ;
var声明的变量会和window有映射关系;
5. 会产生暂时性死区:
>暂时性死区是浏览器的bug:检测一个未被声明的变量类型时,不会报错,会返回undefined
> 例:
console.log(typeof a) //undefined
console.log(typeof a)//未声明之前不能使用
let a
二、解构赋值
* 1、左侧 数据形式 要与 右侧数据形式保持一致;
* 2、在右侧数据值的位置上,对应的在左侧写变量;
* 3、字符串在解构赋值时,形式上可以看成是一个字符数组,或者一个字符对象。可以按照数组,对象的形式进行解构赋值操作;
* 4、数组本身就是一个对象,可以按照key是从0连续增加的对象进行解构赋值;
* 5、有this关键字的不能被解构,会出现指向丢失(当解构的对象方法内部有this关键字参与,该方法不能进行解构,如果强行进行解构,在赋值后,调用时,会导致内部的this指向window)。
var data = {
data: {
songList: [{
name: "周深",
songname: "大鱼海棠"
},
{
name: "蔡徐坤",
songname: "情人"
}]
}
}
var {data: {songList: [{name: [zname]}]}} = data
console.log(zname)
var {data:{songList:[,{ name:cname,songname:csongname}]}}=data
console.log(cname,csongname)
三、函数形参
1、函数形参默认值,必填项必须写在最左边
2、函数的形参,用拓展运算符代替arguments(arguments不是数组,是类数组的对象)
rest参数,形式为“...变量名”,用于获取函数的多余参数,可以用rest参数取代arguments对象的使用。
//解构形参传递
function sum([x,y]){
return x+y
}
sum([1,2])
function fn3({floor,random,min,max},num1,num2){
return [
floor(random()*(max(num1,num2)-min(num1,num2))+min(num1,num2)),
min(num1,num2),
max(num1,num2)
]
}
console.log(fn3(Math,20,15))
四、模板字符串
1、核心设计思想:是在字符串中,通过一些特殊的符号:"${}","{{ }}","<%= %>","<?php ?>"来包裹相应的 语句表达式实现字符串内容的动态拼接,和动态生成,动态删除 “模板引擎”
2、新增字符串操作API
var str = "hello aaa";
console.log(str.includes("h")); //包含返回true 不包含返回false
console.log(str.startsWith("hello")); //返回布尔值,表示参数字符串是否在原字符串的头部。
console.log(str.endsWith("aaa")); //返回布尔值,表示参数字符串是否在原字符串的尾部。
console.log("x".repeat(5)); //返回一个新字符串,表示将原来的字符串重复了若干次
var str1 = " a bc de ";
console.log(str1.trim()); //去掉前面空格
console.log(str1.trimStart());
console.log(str1.trimEnd()); //去掉后面空格
五、数组拓展
1、数组拓展,...arr数组拓展运算符
let arr1 = [1, 2,3, 4, 5, 6];
console.log(...arr1);
//深拷贝
let arr2 = [...arr1];
//数组合并
let arr3 = [...arr1, ...arr2];
2、数组深拷贝,方法 res = copy(argu)
var arr = [{ name: "张三" }, 3, 3];
var arr4 = [...arr];
arr4[0].name = "李四";
console.log(arr[0].name);
注:当数组元素是对象类型数据时,无法直接通过
3、数据深拷贝
function copy(obj){
// 利用构造函数 constructor判断是否为Array类型
var newObj = obj.constructor === Array?[]:{};
// 进行进一步解析
for(var i in obj){
// 判断类型
// arguments.callee==copyObject(obj),一般用于递归调用来减少代码耦合性,
if(typeof obj[i] === 'object') newObj[i] = arguments.callee(obj[i]);
else newObj[i]=obj[i];
}
return newObj;
}
function isObject(type){
// 判断数据类型,如果不是基本数据类型则传入copy方法进一步解析拷贝;否则直接进行拷贝
var data=typeof type === 'object'?copy(type):type;
return data;
}
// 业务
var data1=[{name:"zhang"},1,4,5]
var data2=isObject(data1)
data2[0].name="1111"
console.log(data2)
console.log(data1)
4、数组新增API
1. ES6 将数组形式的对象转成纯数组:Array.from(arr)
2. Array.of() 将传入的参数构建成新的数组
3. 对象方法 arr.find(callback):查找符合callback return条件的 数据
4. arr.flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,
var arrayLike = {
0: 4,
1: 30,
2: 9,
length: 3,
};
//1
// arrayLike = Array.prototype.slice.call(arrayLike); //ES5
arrayLike = Array.from(arrayLike); //ES6
console.log(arrayLike);
//2
var arr = [1, 4, 3];
var arr10 = Array.of(...arr);
console.log(arr10);
//3
var arr = [1, 2, 3, 4, 5, 6];
var res = arr.find((item) => {
return item > 3;
});
console.log(res);
//4
console.log([1, 2, [3, 4]].flat()); //[1,2,3,4]
5、判断是不是数组
//1、instanceof
var a = [];
console.log(a instanceof Array);
//2、ES6
console.log(Array.isArray(a));
//3、ES5
console.log(a.constructor == Array);
//4、ES5
console.log(toString.call(a), toString.call(1, 2));
六、新增数据类型
1、新增变量类型 Symbol类型:表示独一无二
var user = "123";
var user1 = "123";
user == user1; //true
var user = Symbol("baloo");
var user1 = Symbol("baloo");
console.log(user == user1); //false
console.log(user); //不可运算
### 2、新增的set类型(数组的扩展):
主要用于,**非引用类型元素的数组去重**
- 向后追加:set.add()
- 查是否含有:set.has()
- 集合长度:set.size
- 获取所有的value:set.values()
- 获取所有的key:set.keys()
- 迭代器,枚举器:set.next()
- 删除集合中的指定数据:set.delete(num)
- 集合清空:set.clear()
var oSet = new Set([1, 2, 3, 3, 3, 3, 3, 4, 4, 4, 5, 5, 5, 5, 6]);
console.log(oSet);
//向后追加
oSet.add("哈哈");
console.log(oSet);
//查是否含有
console.log(oSet.has(3));
//集合长度
console.log(oSet.size);
//set数据的遍历 key就是value本身
oSet.forEach((key, value) => {
console.log(key, value);
});
//获取所有的value
console.log(oSet.values());
//获取所有的key
console.log(oSet.keys());
var oIter = oSet.values();
//迭代器,枚举器
console.log(oIter.next()); //返回set中第一个数据
console.log(oIter.next()); //返回set中第二个数据
//删除集合中的数据
oSet.delete(5);
console.log(oSet);
//集合清空
oSet.clear();
console.log(oSet);
3、map类型数据(对象数据的扩展)
1、map数据添加的是**键值对集合数据**,特点 key和value
2、可以是**任意的数据类型**
//map使用方式
//1、创建map对象
var oMap = new Map();
//2、添加键值对
var key = { name: "132", age: 12 };
oMap.set(key, "哈哈");
oMap.set([132], "嘿嘿");
console.log(oMap);
//通过key 读取 value
console.log(oMap.get(key));
console.log(oMap.get([132])); //undefined
//查看里面是否包含
console.log(oMap.has(key)); //true
console.log(oMap.has([132])); //false
//遍历
oMap.forEach((value, key, map) => {
console.log(value, key, map);
});
//获取所有的key
console.log(oMap.keys());
//获取所有的value
console.log(oMap.values());
//删除对应的 key=value
oMap.delete(key);
console.log(oMap);
//清空
oMap.clear();
console.log(oMap);
七、for...of,for..in
1、for...of
for...of循环使用的范围:
数组
Set
Map结构
某些类似数组的对象(比如arguments对象、DOM NodeList 对象)
后文的 Generator 对象
字符串
var arr = ['aa', 'bb', 'cc', 'dd'];
//只循环key
for (var key of arr.keys()) {
console.log(key); //0 1 2 3
}
//只循环value,注意数组是没有.values()
for (var value of arr) {
console.log(value);//aa bb cc dd
}
//循环key,value
for (var [key, value] of arr.entries()) {
console.log(key, value);//0 aa 1 bb 2 cc 3 dd
}
2、for...of,for..in区别
for in遍历的是数组的索引(即键名),而for of遍历的是数组元素值。
var arr = ['aa','bb','cc','dd'];
for(var i in arr){
console.log(i);//iarr数组对应的索引: 0 1 2 3
}
for(var i of arr){
console.log(i);//i数组具体的值 aa bb cc dd
}