一、let
1.不允许重复声明
let name = "张三"
let name = "李四"
console.log(name)
2.块级作用域
for(let i=0; i<10; i++){
console.log(i)
}
console.log(i)
//如果在eval中使用let定义变量,那么说变量外部是无法使用的
eval('let num = 10')
console.log(num)
3.不存在变量提升--预解析
console.log(num)
let num = 10
4.不影响作用域链
function f1(){
let num = 10
function f2(){
console.log(num) //10
}
f2()
}
f1()
二、const
- const用来声明一个常量(和let一样,只是不能改值)
1.声明的时候必须要有初始值
const num = 10
console.log(num) //10
2.常量的名称一般[大写]潜规则
const REQ_SUCCESS = 'request_success'
console.log(REQ_SUCCESS) //request_success
3.不能修改常量的值
const age = 10
age = 20
console.log(age)
4.不允许重复声明
const num1 = 10
const num1 = 20
5.块级作用域
function f1(){
const age = 10
}
f1()
console.log(age) //10
6.关于数组和对象的元素的修改
const obj = {}
obj.age = 10
console.log(obj.age)
const arr = []
arr.push(10)
console.log(arr)
三、解构赋值
1. 理解:从对象或数组中提取数据,并赋值给变量(多个)
2. 对象的解构赋值: let {m,n}={n:'a',m:'b'}
3. 数组的解构赋值: let [a,b]=[10,'测试']
4. 用途: 给多个形参赋值
5. 注意:解构赋值对象的时候,写的变量名字一定是对象中存在的属性名字,想要什么属性就写什么属性
1.数组的解构赋值
const arr = ['张三', '李四', '王五', '赵六']
const [name1, name2, name3, name4] = arr
console.log(name1, name2, name3, name4) // '张三', '李四', '王五', '赵六'
2.对象的解构赋值
const obj = {
name: '小明',
age: 20,
gender: '男',
sayHi: function () {
console.log('hello')
}
}
const { name, age, gender, sayHi } = obj
console.log(name, age, gender) // '小明',20,'男'
sayHi()
3.复杂结构的解构赋值
var product = {
name: '手机',
price: 2000,
saleAttr: {
saleAttrValue1: '白色',
saleAttrValue2: '黑色',
saleAttrValue3: '绿色',
},
imgList: [
{
name: '1.jpg',
url: '/src/static/1.jpg'
},
{
name: '2.jpg',
url: '/src/static/2.jpg'
}
]
}
const {
name,
price,
saleAttr: { saleAttrValue1, saleAttrValue2, saleAttrValue3 },
imgList:[img1, img2]
} = product;
console.log(name, price)
console.log(saleAttrValue1, saleAttrValue2, saleAttrValue3)
console.log(img1.name, img1.url)
console.log(img2.name, img2.url)
四、模板字符串
1. 作用:简化字符串的拼接
2. 模版字符串必须用 `` 包含
3. 变化的部分使用 ${xxx}定义
const age = 100
const text = `今年过年,小明的年龄已经是:${age}`;
console.log(text);
document.write(`
<button>1</button>
<button>2</button>
<button>3</button>
<button>4</button>
<button>5</button>
`);
五、箭头函数
1. 作用: 定义匿名函数
2. 基本语法: ()=>{console.log('xxxx')}
3. 一个参数: msg=> msg+2
4. 多个参数: (m,n)=>m+n
5. 函数体不用大括号:默认有返回结果
6. 函数体如果有多个语句,需要使用{}包裹,如果内部有需要返回的值,则手动return
7. 使用场景: 多用来定义回调函数
8. 不能作为构造函数使用
9. 箭头函数的特点:
- 简洁
- 箭头函数没有自己的this,箭头函数的this不是调用的时候决定的,而是在定义的时候处在自己对象就是它的this
- 扩展理解: 箭头函数的this看外层的是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有则this是window
10. 箭头函数中arguments不能使用
11. 存储this的方法
const that = this;
const _this = this;
1.基本语法
const f1 = () => {console.log('hello')}
f1()
2.基本使用
const add = (a, b, c) => {
return a + b + c
};
const result = add(10, 20, 30);
console.log(result) //60
3.一个参数,可以省略前面的小括号
const f2 = a => {
console.log(a) //10
}
f2(10)
4.两个参数,小括号不能省略
const f3 = (a,b) => {
return a+b
}
console.log(f3(10,20)) //30
5.如果没有大括号,表示有返回值
const f4 = (a, b) => a + b
console.log(f4(100, 200)); //300
6. 如果有多条语句,需要使用大括号,如果有返回值自己手动加return
const f5 = (a, b, c) => {
const result = a + b + c
console.log(result) //600
return result
};
console.log(f5(100, 200, 300))
7. 使用场景(定时器,数组中常用方法,事件的回调函数...)
setTimeout(() => {
console.log(this)
console.log('定时器启动了')
}, 1000);
console.log([10, 20, 30].map(item => {
console.log(this)
return item * 2
}));
8. 不能作为构造函数使用
/*
const Person =()=>{
name:'小明'
};
var per = new Person();
console.log(per.name)
*/
9.箭头函数的this是不能改变的
window.name = '小明'
const f6 = () => {
console.log(this.name)
};
const f7 = function () {
console.log(this.name)
};
f6(); //小明
f7(); //小明
var obj = {
name: '大明'
}
f6.call(obj) //小明
f7.call(obj) //大明
10. 箭头函数中arguments不能使用
const f8 =(arguments)=>{
console.log(arguments.length) //undefined
}
f8(1,2,3,4,5)
11.使用场景
// 获取数组的偶数的数据
const result = [1, 2, 3, 4, 5].filter(function (item) {
if (item % 2 === 0) {
return true
} else {
return false
}
})
console.log(result) // [2, 4]
console.log([1, 2, 3, 4, 5, 6, 7, 8].filter(item => item % 2 === 0)) // [2, 4, 6, 8]
六、spread延展运算符
... 扩展运算符(展开运算符),能将数组转换为参数列表
function f1() {
console.log(arguments)
}
const arr = [10, 20, 30];
// 拆包
f1(...arr)
// 展开对象
const obj1 = {
name: '卡卡西',
age: 20
}
const obj2 = {
gender: '男',
weight: '50kg'
}
const obj = {
...obj1,
...obj2
}
console.log(obj) //{name: "卡卡西", age: 20, gender: "男", weight: "50kg"}
可以将数组和对象中的数据进行展开,并且也可以将数据拆包,也可以打包
也可以通过扩展运算符合并两个数组对象
1.数组和对象的合并
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
// 将arr1和arr2合并为一个新的数组
const arr = [...arr1, ...arr2]
console.log(arr) //[1, 2, 3, 4, 5, 6]
2.数组的克隆
const arr3 = [10, 20, 30]
const arr4 = [...arr3]
console.log(arr4) //[10,20,30]
3.伪数组转真数组
const arr5 = document.getElementsByTagName('button')
console.log(arr5 instanceof Array) //false
console.log([...arr5] instanceof Array) //true
七、Set集合介绍及属性和方法
Set()是一种数据结构,内部可以放的内容是可以通过for-of进行遍历的数据(数组,字符串),但是自定义的对象不可以遍历(for-of)
// 定义Set 集合
const set = new Set()
console.log(set)
// 传入数据
const set = new Set([10, 20, 30, 40, 50])
console.log(set) //{10, 20, 30, 40, 50}
console.log(set.size) //5
// 自动去重
const s = new Set();
const s = new Set([10,20,20,30,40]);
console.log(s) //{10, 20, 30, 40}
// Set()中可以放的内容是可以通过for-of进行遍历的数据
// 数组, 字符串可以, 自定义的对象不可以
const s = new Set('abcdef')
const s = new Set([10, 20, 30, 40, 50]);
// 向Set集合中添加一个数据
s.add(100);
// 把Set集合中的一个数据进行删除
s.delete(10);
// 判断Set集合中这个数据是否存在
console.log(s.has(1000));
// 清空集合的
s.clear();
console.log(s);
//size 返回集合的元素个数
console.log(s.size)
// 把数组中重复的数据去掉---只保留数组中不重复的数据
const arr = [10,10,20,30,40,50,50,60,60];
const arr2 = [...new Set(arr)];
console.log(arr2)
console.log([...new Set([10,10,20,20,30])]);
- 案例
// 1. 数组去重
const arr1 = ['张三', '李四', '王五', '赵六', '张三', '小李'];
const arr2 = [...new Set(arr1)];
console.log(arr2); //['张三', '李四', '王五', '赵六', '小李']
// 2. 获取数组中相同的数据---交集操作
var arr3 = [10, 20, 30, 40, 50];
var arr4 = [40, 50, 60, 70];
var arr5 = [...new Set(arr3)].filter(item => new Set(arr4).has(item));
console.log(arr5); //[40,50]
// 3. 获取数组中不同的数据---并集操作
var arr6 = [10, 20, 30, 40];
var arr7 = [10, 20, 50, 60];
var arr8 = [...new Set([...arr6, ...arr7])];
console.log(arr8) //[10,20,30,40,50,60]
// 4. 获取数组中差集(我有的你没有,或者你有的我没有)
var arr9 = [10, 20, 30, 40];
var arr10 = [10, 20, 60, 70];
var arr11 = [...new Set(arr9)].filter(item => !(new Set(arr10).has(item)));
console.log(arr11); //[30, 40]
var arr12 = [...new Set(arr10)].filter(item => !(new Set(arr9).has(item)));
console.log(arr12); //[60, 70]
八、对象扩展
1.Object.is() 判断两个值是否为同一个值
const num1 = 100;
const num2 = 100;
console.log(num1 === num2); //true
console.log(Object.is(num1, num2)); //true
console.log(Object.is(NaN, NaN)); //true
2. Object.assign 对象的合并
Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。
它将返回目标对象。
合并对象,第一个参数是目标对象,第二个参数是要合并的对象,该方法返回的对象就是目标对象,如果合并的对象中有相同的属性会被覆盖
const obj1 = {
name: '小明',
age: 20
};
const obj2 = {
gender: '男',
height: '157'
};
Object.assign(obj1, obj2);
console.log(obj1); //{name: "小明", age: 20, gender: "男", height: "157"}
3.3__proto__、setPrototypeOf、 setPrototypeOf可以直接设置对象的原型
const obj = {
name: 'atguigu'
};
const obj2 = {
age: 8
};
obj2.__proto__ = obj;
console.log(obj2);
九、深浅拷贝
1.深拷贝
- 更深层次的拷贝,指向的不是一块内存地址
- 会另外创造一个一摸一样的对象,新对象跟原来的对象不共享内存(指向的不是同一个内存地址),
修改新对象不会改变原对象
//1、JSON.parse(JSON.stringify(obj)),不可以拷贝undefined、function、RegExp等类型的
var obj = {
a:'hello',
b:{
name:'lily',
age:21
},
c:[1,2,3]
};
var obj1 = JSON.parse(JSON.stringify(obj));
//2、递归回调,实现深度拷贝
// 定义一个深拷贝函数 接收目标target参数
function deepClone(target) {
// 定义一个变量
let result;
// 如果当前需要深拷贝的是一个对象的话
if (typeof target === 'object') {
// 如果是一个数组的话
if (Array.isArray(target)) {
result = []; // 将result赋值为一个数组,并且执行遍历
for (let i in target) {
// 递归克隆数组中的每一项
result.push(deepClone(target[i]))
}
// 判断如果当前的值是null的话;直接赋值为null
} else if(target===null) {
result = null;
// 判断如果当前的值是一个RegExp对象的话,直接赋值
} else if(target.constructor===RegExp){
result = target;
}else {
// 否则是普通对象,直接for in循环,递归赋值对象的所有值
result = {};
for (let i in target) {
result[i] = deepClone(target[i]);
}
}
// 如果不是对象的话,就是基本数据类型,那么直接赋值
} else {
result = target;
}
// 返回最终结果
return result;
}
2.浅拷贝
- 指向的是同一块内存地址,修改会改变原来的数据
- 只复制指向某个对象的指针而不复制对象本身,新旧对象还是共享同一块内存
//1.赋值
let obj = {name:'dx',age:'18'}
let obj1 = obj
//2.assign方法实现浅拷贝
var obj1 = { name: "lily" };
var obj2 = Object.assign({}, obj1);
obj2.name = "bob";
console.log(obj1.name); //lily
console.log(obj2.name); //bob
// 3.Array.prototype.slice
const arr1 = [
'yang',
{
value: 123
}
];
const arr2 = arr1.slice(0);
arr2[1].value = 456;
// 因为数组的第一层有引用类型,浅拷贝无法实现
console.log(arr2); // ["yang", {value: 456}]
console.log(arr1); // ["yang", {value: 456}]
arr2[0] = 'haha';
console.log(arr2); // ["haha", {value: 456}]
console.log(arr1); // ["yang", {value: 456}]
//4.Array.prototype.concat
const arr1 = [
'yang',
{
value: 123
}
];
const arr2 = [].concat(arr1);
arr2[1].value = 456;
//因为数组的第一层有引用类型,浅拷贝无法实现
console.log(arr2); // ["yang", {value: 456}]
console.log(arr1); // ["yang", {value: 456}]
arr2[0] = 'haha';
console.log(arr2); // ["haha", {value: 456}]
console.log(arr1); // ["yang", {value: 456}]