一.let关键字
1.1 var的弊端
使用var关键字声明变量的弊端:
1、var声明的变量有预解析,造成 逻辑混乱,可以先使用,后声明
2、var可以重复定义同一个变量,逻辑错误,第二次应该是修改变量,而不是定义
3、var用在for循环条件中,造成for 循环的污染的问题
4、var 声明的变量没有块级作用域(ES5中的作用域:全局和局部)
<script>
/*
Var的弊端
1.var会有预解析,在变量声明之前可以使用
*/
//1.var会有预解析,在变量声明之前可以使用
console.log(str1); //undefined
var str1 = "hello";
//2.var可以重复定义
var num1 = 10;
var num1 = 30;
console.log(num1);
//3.块级作用域的问题:ES5没有块级作用域,只有全局作用域和函数作用域
{
var str2 = 'wrold';
}
console.log(str2);
//4.for循环中变量污染
var i;
for (i = 0; i < 4; i++) {
console.log(i); //0 1 2 3
}
console.log(i); //4,变量污染
</script>
1.2 ES6变量声明:let
let 关键字用来声明变量,使用 let 声明的变量有几个特点:
- ==不允许重复声明==
- ==块儿级作用域==
- ==不存在变量提升==
- ==不影响作用域链== ==应用场景:以后声明变量使用 let==
/*
let关键字的使用:
1.let取消预解析,变量声明不会提升,必须先声明然后再使用
2.let不可以重复定义
3.let有块级作用域
4.解决for循环里的变量污染
5.let不影响作用域链
*/
//1. let取消预解析, 变量声明不会提升, 必须先声明然后再使用
//console.log(str); //Uncaught ReferenceError: Cannot access 'str' before initialization
let str = "hello";
// 2. let不可以重复定义
let str2 = "world";
//let str2 = "jason";
//console.log(str2); //Uncaught SyntaxError: Identifier 'str2' has already been declared
//3.let有块级作用域
{
let num = 10;
}
//console.log(num); //Uncaught ReferenceError: num is not defined
//4.解决for循环里的变量污染
for (let i = 0; i < 4; i++) {
console.log(i); //0 1 2 3
}
//console.log(i); //Uncaught ReferenceError: i is not defined
//5.let不影响作用域链
let school = "atguigu"; {
let school = "尚硅谷";
function fn() {
console.log(school); //"尚硅谷"
}
fn();
}
console.log(school); //"atguigu"
二.块级作用域
块指的是代码块,一对 {}
之间就是一个代码块。
变量的有效范围只在这对 大括号 之间,就是块级作用域
块级作用域非常有必要:
var btns = document.querySelectorAll('button')
for(var i = 0; i < btns.length; i++){
btns[i].onclick = function(){
console.log(i)
}
}
此时我们点击按钮,输出的i不会是每个按钮对应的按钮,而是按钮的个数。就是因为for里面的变量是var声明的,没有形成块级作用域,每次访问i都是访问的全局的i。如果我要在事件里面得到按钮的索引,就需要别的方法来实现。
如果我们换成let
let btns = document.querySelectorAll('button')
for(let i = 0; i < btns.length; i++){
btns[i].onclick = function(){
console.log(i)
}
}
此时我们点击按钮,就能输出按钮对应的索引了。这是因为我们使用了let关键字,let会在{}之间形成一个块级作用域,for循环执行多少次,我们就会形成多少个块级作用域,每个i对应1个,当我们在事件里面获取i的时候,i会到事件函数的上级作用域找,刚好就是每个i对应的块级作用域。我们就简单地得到了每个按钮对应的索引。
所以,let的特点:
1、let声明的变量没有预解析,不会有变量提升
2、let不可以重复定义同一个变量
3、let用在for循环条件中,不会造成for 循环的污染的问题
4、let声明的变量有块级作用域(ES6中的作用域:全局和局部还有块级作用域)
三.const关键字
==const 关键字用来声明常量==,const 声明有以下特点
- const 一旦声明就必须赋值,不赋值就会报错
- 标识符一般为大写(潜规则,因为是常量,常量一般是大写)
- const不允许重复声明
- const拥有块级作用域
- 一旦赋值就不能修改(基本数据类型)
- const修改引用数据类型
- 直接修改引用数据类型的引用地址:不可以,会报错:Uncaught TypeError: Assignment to constant variable.
- const修改数组里的数据:可以 应用场景:声明对象类型使用 const ,非对象类型声明选择 let
/*
const关键字
1.const 一旦声明就必须赋值,不赋值就会报错
2.const一旦赋值就不能修改
3.const拥有块级作用域
4.const修改引用数据类型(对象)
4.1 const直接修改引用类型的地址:不允许
4.2 const修改引用类型的里面的数据:可以
5.const修改引用数据类型(数组)
5.1 const直接修改数组:不允许
5.2 const修改数组里的数据:可以
*/
//1.const 一旦声明就必须赋值,不赋值就会报错
//const str; //Uncaught SyntaxError: Missing initializer in const declaration
//2.const一旦赋值就不能修改
// const str = "hello";
// str = "hello world";
// console.log(str); //Uncaught TypeError: Assignment to constant variable.
// 3.const拥有块级作用域
// {
// const num = 10;
// }
// console.log(num); //Uncaught ReferenceError: num is not defined
//4.const修改引用数据类型(对象)
//4.1 const直接修改引用类型的地址:不允许
const obj = {
name: 'jason',
age: 18
}
// obj = {
// genger: 'male'
// }
//console.log(obj); //04. const关键字.html: 75 Uncaught TypeError: Assignment to constant variable.
//4.2 const修改引用类型的里面的数据:可以
obj.name = "grace";
console.log(obj); //{name:'grace',age:18}
//5.const修改引用数据类型(数组)
//5.1 const直接修改数组:不允许
const arr = [1, 2, 3, 4, 5];
// arr = [1, 1, 1];
// console.log(arr); //Uncaught TypeError: Assignment to constant variable.
//5.2 const修改数组里的数据:可以
arr[0] = 10;
console.log(arr); //[10,2,3,4,5]
四.模板字符串
在es5中,当我们需要把多个字符串和多个变量拼接到一起的时候,写法还是比较复杂的
let name = '狗蛋',age = 12,gender = '男'
let str = "大家好,我叫" + name + ",今年" + age + "岁了,我是一个" + gender + "孩子"
所以在es6中为了解决这个问题,提供了一种模板字符串
固定用法:
`固定字符${变量或者表达式}`
- 在模板字符串中,可以解析
${}
之间的变量或者表达式 - 在整个字符串中允许换行
所以当我们在es6中拼接字符串
let name = '狗蛋',age = 12,gender = '男'
let str = `大家好,我叫${name},今年${age}岁了,我是一个${gender}孩子`
五.变量的解构赋值
ES6 允许按照一定模式,从数组或对象中提取值,对变量进行赋值,这被称为解构。
目的:简化代码。
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构赋值。
5.1 对象的解构赋值
/*
对象的解构赋值
*/
var obj = {
name: "jason",
age: 18,
doWhat: function () {
console.log("program");
}
}
//1.在ES5里
/* let name = obj.name;
let age = obj.age;
let doWhat = obj.doWhat; */
//2.全部解构:等号左边的变量要和属性名相同
/* let {
name,
age,
doWhat
} = obj;
console.log(name);
console.log(age);
console.log(doWhat); */
//3.部分解构
/* let {
name
} = obj;
console.log(name); */
//4.解构之后重新命名
let {
name: itsName
} = obj
console.log(itsName);
//5.将现有的对象的方法赋值到某个变量
let {
random
} = Math;
let num = random();
console.log(num);
5.2 数组解构
/*
数组解构
*/
var arr = [1, 2, 3, 4, 5];
//1.完全解构
/* let [
a,
b,
c,
d,
e,
f
] = arr;
console.log(a); //1
console.log(b); //2
console.log(c); //3
console.log(d); //4
console.log(e); //5
console.log(f); //undefined */
//2.部分解构
let [a, , , , e] = arr;
console.log(a); //1
console.log(e); //5
// 3.复合解构
let arr2 = [1, 2, [10, 20, 30]];
let [j, k, [x, y, z]] = arr2;
console.log(j); //1
console.log(k); //2
console.log(x); //10
console.log(y); //20
console.log(z); //30
5.3 字符串的解构
- 应用:==不需要变量直接利用ES6语法交换变量==
/*
字符串的解构
*/
let str = "liu";
let [x, y, z] = str;
console.log(x, y, z); //l i u
str[1] = 's'; //无法修改
console.log(str); //liu
console.log(str[1]); //l
//应用:交换字符串的位置
let str1 = "hello";
let str2 = "world";
[str2, str1] = [str1, str2]; //不需要变量直接利用ES6语法交换变量
console.log(str1, str2); //world hello
注意:频繁使用对象方法、数组元素,就可以使用解构赋值形式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>04.ES6里面的结构赋值</title>
</head>
<body>
<script>
/*
ES6里面允许按照一定的模式从数组和对象中提取值,对变量进行赋值,这被称为结构赋值
*/
//1.数组的解构
let F4 = ["小沈阳", "刘能", "赵四", "宋小宝"];
let [xiao, liu, zhao, song] = F4;
console.log(xiao);
console.log(liu);
console.log(zhao);
console.log(song);
//2.对象的解构
let obj = {
name: "赵本山",
age: 70,
xiaopin: function () {
console.log("昨天,今天,明天");
}
}
let {
name,
age,
xiaopin
} = obj;
console.log(name);
console.log(age);
console.log(xiaopin);
//调用
xiaopin();
</script>
</body>
</html>
六.简化对象写法
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。这样的书写更加简洁。
当我们在以前定义对象字面量的时候,如果有如下代码
let name = '狗蛋',age = 12,gender = '男'
let obj = {
name : name,
age : age,
gender : gender
}
此时我们发现obj的属性名和变量是同样的,可以在es6中简化为:
let obj = {name,age,gender}
也就是说,如果一个对象的属性名和外面的一个变量名同名,可以直接交变量名作为属性名,并会自动地把变量的值作为属性的值
方法上面也可以进行简化:
/*
1.对象的简化写法:
如果一个对象的属性名和外面的一个变量名同名,可以直接交变量名作为属性名,并会自动地把变量的值作为属性的值
2.方法的简化:
3.this的指向:
3.1 直接调用this:指向window
3.2 函数内部调用,this指向window
3.3 对象调用:this指向当前调用的对象
*/
let name = "张涛";
let age = 18;
let work = "华为";
/* let obj = {
name,
age,
work
};
console.log(name, age, work); */
let func = function () {
console.log(this);
}
//func(); //1.直接调用this:指向window 2.函数内部调用,this指向window
let obj = {
name,
age,
work,
func
};
obj.func(); //3.对象调用:this指向当前调用的对象
注意:对象简写形式简化了代码,所以以后用简写就对了
七.函数参数默认值和参数解构
7.1 函数形参默认值
es5里面如果我们想要实现参数可以省略,我们有一个办法是这样做
function add(a,b,c,d){
a = a || 0;
b = b || 0;
c = c || 0;
d = d || 0;
return a + b + c + d;
}
此时我们可以把给了默认值的参数省略
add(10,20) // 30
add(10,20,30) // 60
但是这样的做法比较麻烦,es6中提供了一种更加方便的方式,专门实现参数默认值。参数有了默认值之后就可以在调用的时候省略。
funciton 函数名(参数=默认值){ // 注意当 参数 为 undefined 时 参数 赋值为 默认值
}
上面的例子就可以必成:
function add(a=0,b=0,c=0,d=0){
return a + b + c + d;
}
7.2 函数参数的解构赋值
函数参数解构
// 参数是一组有次序的值
function f([x, y, z]) {
console.log(x, y, z);
}
f([1, 2, 3]);
// 参数是一组无次序的值
function fn({x, y, z}) { // {x, y, z} = obj 解构
console.log(x, y, z);
}
fn({z: 4, x: 5, y: 6});
7.3 解构赋值指定参数的默认值
function func2({name, age} = {}){ //防止不传实参时候的报错
console.log(name, age);
}
func2(); //undefined undefined
// func2(); //相当于传了一个null {name, age}=null 就会报错
// func2({}); //不会报错,输出:undefined undefined
function func2({name="luowowo", age=11} = {}){ //指定默认值
console.log(name, age);
}
func2(); //luowowo 11
八.模板字符串
模板字符串(template string)是增强版的字符串,用反引号(`)标识,特点:
- 字符串中可以出现换行符
- 可以使用 ${xxx} 形式输出变量
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>05.ES6中的模板字符串</title>
</head>
<body>
<h1>静夜思</h1>
<p>
<h3>李白</h3>
</p>
<h2>床前明月光</h2>
<h2>疑是地上霜</h2>
<h2>举头望明月</h2>
<h2>低头思故乡</h2>
<script>
/*
ES6中的模板字符串:双引号,单引号,新增反引号
*/
//1.可以定义字符串
let str = `我是一个字符串`;
console.log(str);
//2.反引号可以换行
let JYS = `
<h1>静夜思</h1>
<p>
<h3>李白</h3>
</p>
<h2>床前明月光</h2>
<h2>疑是地上霜</h2>
<h2>举头望明月</h2>
<h2>低头思故乡</h2>
`
console.log(JYS);
//3.变量拼接
let name = "grace";
let loveWho = `${name}是我最喜欢的女人`;
console.log(loveWho);
</script>
</body>
</html>
注意:当遇到字符串与变量拼接的情况使用模板字符串
九.==箭头函数==
ES6 允许使用 “箭头”(=>)简化函数的定义。
箭头函数本质也是函数,它出现的目的是为了让我们在使用回调函数的时候更简单
9.1 箭头函数的语法
固定语法:
(参数) => { 函数体 }
ES6 允许使用「箭头」(=>)定义函数。
let fn = (arg1, arg2, arg3) => {
return arg1 + arg2 + arg3;
}
9.1.1 箭头函数的注意点:
- 如果形参只有一个,则小括号可以省略
- 函数体如果只有一条语句,则花括号可以省略,函数的返回值为该条语句的执行结果
- 如果函数体里面只有一个语句,可以省略大括号不写, 并且他会默认返回 => 符号后面的数据。
- 如果函数体有多个语句,则不能省略大括号。
- 箭头函数 this 指向声明时所在作用域下 this 的值
- 箭头函数不能作为构造函数实例化
- 不能使用 arguments,可以用rest参数替代
- 如果函数体只有一个语句,且返回一个对象,建议是,不要写简写的方式。
注意:箭头函数不会更改 this 指向,用来指定回调函数会非常合适
代码示例:
// 无参数无返回
let func11 = () => console.log('func11');
func11();
// 无参数有返回
let func22 = () => 'func22';
console.log(func22());
// 有参数无返回
let func33 = x => console.log('func33', x);
func33(2);
// 有参数有返回
let func44 = (x, y) => {
let sum = x + y;
return sum + 'func44';
};
console.log(func44(1, 2));
注意:
// 如果return的是单一个对象,则需要加上大括号和return,例如:
// let func55 = (x, y) => {a:,x b:y}; //报错
let func66 = (x, y) => {
return { a: x, b: y };
};
console.log(func66(5, 8));
// 箭头函数不可以使用 arguments 获取参数列表,可以使用 rest 参数代替。
let func=(a,b)=>{
console.log(a,b);
console.log(arguments);
}
func(1,2)// 这种方式获取不到实参列表
let fun=(...value)=>console.log(value);
fun(1,2)//[ 1, 2 ]
9.1.2 使用场景(回调函数):
// 定时器中的回调函数
setInterval(() => {
console.log("我用了箭头函数");
}, 1000);
// forEach中的回调函数
var arr = [22, 32, 11, 3, 5, 7, 88];
arr.forEach(item => console.log(item));
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>07.箭头函数的使用</title>
</head>
<body>
<script>
/*
箭头函数的使用:ES6允许箭头函数的使用
*/
/* let add = (a, b) => {
return a + b;
}
let result = add(1, 2);
console.log(result); */
//1.this是静态的,this始终指向函数声明时所在作用域的this的值
function getName() {
console.log(this.name);
}
let getName2 = () => {
console.log(this.name);
}
//设置window的name属性
window.name = "尚硅谷";
const school = {
name: "atguigu",
}
//1.1直接调用
// getName();//尚硅谷
// getName2();//尚硅谷
//12 call方法调用
getName.call(school); //atguigu
getName2.call(school); //尚硅谷
//2.不能作为构造函数实例化对象
let person = (name, age) => {
this.name = name;
this.age = age;
}
//let me = new person("xiao", 30);
//console.log(me); //07.ES6中箭头函数.html:46 Uncaught TypeError: person is not a constructor
//3.不能使用arguments变量
let fn = () => {
//console.log(arguments); //07.ES6中箭头函数.html:51 Uncaught ReferenceError: arguments is not defined
}
fn(1, 2, 3);
//4.箭头函数的简写
//4.1 省略小括号,当形参有且只有一个时
let add = a => {
return a + a;
}
let sum = add(2);
console.log(sum);
//4.2 省略大括号(并且可以省略return关键字),当代码体只有一条语句的时候
let pow = a => a * a;
let mi = pow(3);
console.log(mi);
</script>
</body>
</html>
9.2 箭头函数中的this
9.2.1 this指向总结:
- 全局使用(函数全局调用)指向window
- 对象调用指向该对象(事件中的事件源)
- 箭头函数没有自己的作用域,即箭头函数 this 指向其外层作用域
var name = "windowName";
var obj = {
name: "奶茶",
fn: function () {
console.log(this.name);
},
};
obj.fn();
var obj2 = {
name: "绿茶",
fn2: () => {
console.log(this.name);
},
};
obj2.fn2();
//所以创建字面量对象,不适合书写箭头函数
9.2.2 在dom操作中使用箭头函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
.box{
width: 200px;
height: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div id="odiv" class="box"></div>
<script>
var obj = document.getElementById("odiv");
obj.onclick = function () {
// setTimeout(function () {
// console.log(this);
// this.style.width = "300px"; //修改不了
// }, 1000);
setTimeout(() => {
console.log(this);
this.style.width = "300px"; //修改成功
}, 1000);
};
</script>
</body>
</html>
6.1 箭头函数的实践
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>08.箭头函数的实践</title>
</head>
<style>
.div {
width: 200px;
height: 200px;
border: 1px solid #ccc;
background: #ccc;
}
</style>
<body>
<div class="div"></div>
<script>
/*
需求一:点击两秒后盒子变成紫色
需求二:从数组中返回偶数的元素
*/
//需求一:点击两秒后盒子变成紫色
//1.1 普通写法
let div = document.querySelector(".div");
/* div.onclick = function () {
setTimeout(function () {
div.style.backgroundColor = "purple";
}, 100)
} */
//1.2 this写法
/* div.onclick = function () {
setTimeout(function () {
console.log(this); //这里的this指向window
this.style.backgroundColor = "purple";
}, 100)
} */
//1.2 解决办法
div.onclick = function () {
let _this = this;
console.log(_this);
setTimeout(function () {
console.log(_this); //这里的this指向盒子本身
_this.style.backgroundColor = "purple";
}, 100)
}
//1.3 ES6箭头函数写法
/* div.addEventListener("click", function () {
setTimeout(() => {
//这里的this是静态的,会找到外层的函数div
this.style.backgroundColor = "purple";
}, 200);
}); */
//需求二:从数组中返回偶数的元素
/*
let arr = [1, 2, 5, 6, 8, 9, 10, 7, 2, 20, 30, 15];
let newArr = [];
arr.forEach(function (item, index) {
if (item % 2 == 0) {
newArr.push(item);
}
})
console.log(newArr);
*/
/* const arr = [1, 2, 5, 6, 8, 9, 10];
const result = arr.filter(function (item, index) {
if (item % 2 === 0) {
return true;
} else {
return false;
}
})
console.log(result); */
//简便一
/* const result = arr.filter(item => {
if (item % 2 === 0) {
return true;
} else {
return false;
}
})
*/
//简便二
/* const result = arr.filter(item => item % 2 === 0)
console.log(result); */
/*
总结:箭头函数适合的场景
1.箭头函数适合与this无关的回调:定时器,数组的方法回调
2.箭头函数不适合于this有关的回调:事件回调,对象的方法
*/
</script>
</body>
</html>
6.2 箭头函数的默认值
/*
函数参数的默认值:
1.形参初始值具有默认值的参数,一般位置要靠后(潜规则)
*/
//1.形参初始值具有默认值的参数,一般位置要靠后(潜规则)
// function add(a, b, c = 10) {
// return a + b + c;
// }
// let result = add(1, 2);
// console.log(result);
6.3 箭头函数与结构赋值的使用
//2.与结构赋值联合使用
function connect({
host,
username,
password,
port
}) {
console.log(host);
console.log(username);
console.log(password);
console.log(port);
}
connect({
host: "localhost",
username: "root",
password: "root",
port: 3306,
});
十.rest 参数和拓展运算符
10.1 rest参数
arguments 对象:
function fn(){
console.log(arguments);// 伪数组
}
fn(10, 20, 30, 50, 60);
ES6提供了新的方法:使用rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
注意,rest 参数之后不能再有其他参数(即只能是最后一个参数),否则会报错。
function func( a, b ,...rest){ // 把剩余的参数都交给rest
console.log(rest);
}
func(10, 20, 30, 50, 60);
function func2(...rest){ //rest 接收所有参数作为一个数组
rest.forEach(function (item) {
console.log(item);
});
}
func2(60, 70, 80, 90);
// 报错
function f(a, ...b, c) {
// ...
}
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
注意:rest 参数非常适合不定个数参数函数的场景
//1.ES5的方式:arguments
function getArr() {
console.log(arguments); //类数组
}
getArr(1, 2, 3, 4, 5)
//2.ES6:rest方法:
//2.1 rest必须写在最后面, 且rest是一个真正的数组
function add(x, y, ...rest) {
//console.log(x, y, ...rest);
console.log(x, y); //1 2
rest.forEach((item) => {
console.log(item); //3 4 5
})
}
add(1, 2, 3, 4, 5)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>10.rest参数</title>
</head>
<body>
<script>
/*
ES6中引入rest参数,用来代替arguments参数
*/
//1.ES5获取实参的方式
let func = function () {
console.log(arguments); //是一个对象
}
func("小沈阳", "宋小宝", "刘能", "尼古拉斯舞王");
//2.ES6中rest方式
//2.1 rest参数必须放到参数最后
function date(a, b, ...args) {
console.log(a);
console.log(b);
console.log(args); //是一个数组
}
date("小沈阳", "宋小宝", "刘能", "尼古拉斯舞王");
</script>
</body>
</html>
10.2、拓展运算符
ES6中的扩展运算符是一个非常有用的运算符号,可以用来快速展开数组,对象...
它的作用就是可以将数组或者对象展开,拆开成为一个一个单独的数据。
// 快速将一个数组拆开成一个一个的元素
let arr = [1, 2, 3, 4]
console.log(...arr)
// 快速将一个对象里面的数据复制一份到一个新的对象里面
let obj = { name: '狗蛋', age: 12, gender: '男' }
console.log({id:1,birthday:'2020-02-02', ...obj})
// 将一个字符串拆开成为多个单独的字符
let str = 'abc'
console.log(...str)
使用场景:
// 1、数组中的值作为函数参数使用
let arr1 = [10, 20, 30];
function func(a, b, c){
console.log(a,b,c)
}
func(...arr1); //等效于:func(10,20,30); 输出结果10 20 30
// 2、合并数组
let arr2 = [40, 50, 60];
let newArr = [...arr1,...arr2]; // 等效于 [ 10, 20, 30, 40, 50, 60 ]
console.log(newArr); //[ 10, 20, 30, 40, 50, 60 ]
// 3、合并对象
let obj1 = {
name:"luowowo",
age:"11",
};
let obj2 = {
email:"luowowo@163.com",
};
let newObj = {...obj1,...obj2}; // 等效于{ name: 'luowowo', age: '11', email: 'luowowo@163.com' }
console.log(newObj); //{ name: 'luowowo', age: '11', email: 'luowowo@163.com' }
// 4、es6中另一个合并对象的方法
let newObj2 = Object.assign({},obj1,obj2); // 把第二个及第二个以上的参数都合并到第1个上面去。
console.log(newObj2); //{ name: 'luowowo', age: '11', email: 'luowowo@163.com' }
10.2.1 扩展运算符的应用
-
数组的合并
-
//1.数组的合并 let xyj = ["孙悟空", "猪八戒", "沙和尚", "唐僧", "白龙马"]; let hl = ["贾宝玉", "林黛玉", "薛宝钗"]; let con=[...xyj,...hl]; console.log(con);
-
-
数组的克隆
-
//2.数组的克隆 let hl = ["贾宝玉", "林黛玉", "薛宝钗"]; let newHl = [...hl]; console.log(newHl);
-
-
伪数组转换为真数组
-
//3.将伪数组转换为真数组 let divs = document.querySelectorAll(".div"); let arrDiv = [...divs]; console.log(arrDiv);
-
10.3、...在解构赋值中的使用
- 针对数组解构
let [a, b, c, ...arr] = [1, 2, 3, 4, 5, 6, 7];
console.log(a, b, c, arr); // a = 1, b = 2, c = 3, arr = [4,5,6,7]
按照顺序把数组里面的元素解构到等号左边的变量里面,当左边的变量不够,会把剩下的数据放到arr这个数据里面,此时arr是就一个新的数组。
- 解构字符串
let str = "abcde";
let [a, b, c, ...strArr] = str;
console.log(a, b, c, strArr); // a = 'a',b='b',c='c',strArr=['d','e']
十一.练习
11.1 练习一:指定日期返回今年的第几天?
- 解法一:常规方法累加
/*
指定日期返回今年的第几天?
*/
function getSomeDay(date) {
let year = date.getFullYear()
let month = date.getMonth() + 1;
let someDate = date.getDate();
let monthDate = 0; //记录每月有多少天
let sumDate = 0; //记录是今年的第多少天
for (let i = 1; i < month; i++) {
if (i == 1 || i == 3 || i == 5 || i == 7 || i == 8 || i == 10 || i == 12) {
monthDate = 31;
} else if (i == 4 || i == 6 || i == 9 || i == 11) {
monthDate = 30;
} else {
//二月
year % 4 === 0 ? monthDate = 29 : monthDate = 28
}
sumDate += monthDate;
}
sumDate += someDate;
return sumDate;
}
let date = new Date("2020-06-02");
console.log(date.toString() + "是今年的第", getSomeDay(date) + "天"); //31+29+31+30+31+2=154
- 解法二:时间戳相减
//解法二:时间戳相减
function getCurrentDay(date) {
let year = date.getFullYear();
let newDate = new Date(year.toString()).getTime() //获得新年第一天八点的日期
let unixDate = date.getTime();
let unixCha = unixDate - newDate; //时间差
let day = Math.ceil(unixCha / 1000 / 60 / 60 / 24) + 1;
return day
}
let date = new Date("2020-06-02");
console.log(date.toString() + "是今年的第" + getCurrentDay(date) + "天");//154
- 解法三:
function getSomeDay(date) {
let year = date.getFullYear()
let month = date.getMonth() + 1;
let someDate = date.getDate();
let monthDate = 0; //记录每月有多少天
let sumDate = 0; //记录是今年的第多少天
for (let i = 1; i < month; i++) {
switch (i) {
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
monthDate = 31;
break;
case 2:
year % 4 === 0 ? monthDate = 29 : monthDate = 28;
break;
case 4:
case 6:
case 9:
case 11:
monthDate = 30;
break;
}
sumDate += monthDate;
}
sumDate += someDate;
return sumDate;
}
let date = new Date("2020-06-02");
console.log(date.toString() + "是今年的第", getSomeDay(date) + "天"); //31+29+31+30+31+2=154
11.2 练习二:使用Math对象,制作一个十六进制随机颜色
/*
练习二:十六进制随机颜色
题目描述:使用Math对象,制作一个十六进制随机颜色
十六进制:123456789abcdef
*/
//1.写出随机数的函数
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
//2.封装十六进制方法,并设置body背景颜色
function getRandomColor() {
let arr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'a', 'b', 'c', 'd', 'e', 'f'];
let str = "";
for (let i = 0; i < 6; i++) {
let randomNum = getRandom(0, 15);
str += arr[randomNum];
}
str = "#" + str.toString();
let body = document.querySelector("body");
body.style.backgroundColor = str;
console.log(str);
}
//3.定时器驱动方法
setInterval(() => getRandomColor(), 1000);
11.3 练习三:练习三:判断字符串"dsejscnesjcnssdoisc"中哪个字符出现次数最多并计算次数
let str = "dsejscnesjcnssdoisc";
let obj = {};
for (let i = 0; i < str.length; i++) {
let char = str.charAt(i);
if (obj[char]) {
obj[char]++; //把字符都放进对象里
} else {
obj[char] = 1;
}
}
console.log(obj);
let c = '';
let count = 0; //记录次数
for (item in obj) {
if (obj[item] > count) {
count = obj[item];
c = item;
}
}
console.log("dsejscnesjcnssdoisc" + "出现字符次数最多的是" + c + "出现次数为" + count);
let str = "dsejscnesjcnssdoisc";
let arr = [...str];
let obj = {};
arr.forEach((item) => {
if (obj[item]) {
obj[item]++;
} else {
obj[item] = 1
}
});
console.log(obj);
let count = 0;
let c = '';
for (k in obj) {
if (obj[k] > count) {
count = obj[k];
c = k
}
}
console.log("dsejscnesjcnssdoisc" + "出现字符次数最多的是" + c + "出现次数为" + count);