前面的内容主要讲的是JavaScript基础内容,想要更加了解前端的小朋友们,需要再继续努力,我们开始向JavaScript高级内容出发了呦,不要掉队啦!
语法:
var 变量 = 值;
var 声明的变量没有块级作用域(ES5中的作用域:全局和局部)
1、可以先使用,后声明
2、可以重复定义同一个变量,逻辑错误,第二次应该是修改变量,而不是定义
3、var用在for循环条件中,造成for 循环的污染的问题
4、var 声明的变量没有块级作用域(ES5中的作用域:全局和局部)
语法:
let 变量 = 值;
ES6中为了统一并提高代码的安全性,引入了let关键字来代替var声明变量
特点:
1、let声明的变量没有预解析,不会有变量提升
2、同一作用域let不可以重复定义同一个变量
3、let用在for循环条件中,不会造成for 循环的污染的问题
4、let声明的变量有块级作用域(ES6中的作用域:全局和局部还有块级作用域)
块指的是代码块,一对 { } 之间就是一个代码块。变量的有效范围只在这对 大括号 之间,就是块级作用域。
var 和 let都可以用来声明变量,当然,它们会有不同点:
var的声明
var btns = document.querySelectorAll('button')
for(var i = 0; i < btns.length; i++){
btns[i].onclick = function(){
console.log(i)
}
}
console.log(i) //btns.length
let声明
let btns = document.querySelectorAll('button')
for(let i = 0; i < btns.length; i++){
btns[i].onclick = function(){
console.log(i)
}
}
console.log(i) //undefined
ES6中,const关键字来声明一个只读的常量
常量具备以下特点:
语法:
const 常量名 = 值;
语法:
`固定字符${变量或者表达式}`
例如:
let name = '狗蛋',age = 12,gender = '男'
// 字符串拼接
let str = "大家好,我叫" + name + ",今年" + age + "岁了,我是一个" + gender + "孩子"
// 模板字符串
let str2 = `大家好,我叫${name},今年 ${age}岁了,我是一个${gender}孩子`
特点:
在模板字符串中,可以解析 ${ } 之间的变量或者表达式
在整个字符串中允许换行
ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构。
let obj = {
name: "luowowo",
age:11,
email:"[email protected]"
};
// 取出所有属性并赋值:
// let name = obj.name;
// let age = obj.age;
// let email = obj.email;
// 现在只需要(等效于上面的写法):
// 等号左边的变量要和对象里面的属性同名,否则没法解构出来
// let {name, email, age} = obj; //{ }中的变量名和obj的属性名一致 完全解构
// 部分解构
// let {name} = obj; // 部分解构
//解构之后重命名
let {name:itsName} = obj; 解构之后重命名为itsName
//将现有对象的方法,赋值到某个变量
let {random}=Math;
console.log(random)//[Function: random]
在ES6中,对象的写法发生了些改变,对象也可以简写
let name = '小龙女',age = 12,gender = '男'
obj的属性名和变量是同样的,可以在es6中简化为:
let obj = {name,age,gender}
如果一个对象的属性名和外面的一个变量名同名,可以直接将变量名作为属性名,并会自动地把变量的值作为属性的值
let arr1 = [10, 20, 30];
let [a, b, c , d] = arr1;
// 完全解构
console.log(a); //10
console.log(b); //20
console.log(c); //30
// 若解构不成功,变量的值就等于 undefined
console.log(d); //undefined
// 部分解构
let [e] = arr1;
console.log(e); //10
let [ , ,f] = arr1;
console.log(f); //30
// 复合解构
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
let string1 = "xyz";
let [a,b,c] = string1;
console.log(a); //x
console.log(b); //y
console.log(c); //z
string1[1] = "Y";
console.log(string1); // xyz 无法修改
console.log(string1[1]); // y
函数参数可以给默认值
ES5的方法:
function add(a,b,c,d){
a = a || 0;
b = b || 0;
c = c || 0;
d = d || 0;
return a + b + c + d;
}
ES6的方法:
funciton 函数名(参数=默认值){ // 注意当 参数 为 undefined 时 参数 赋值为 默认值
}
function add(a=0,b=0,c=0,d=0){
return a + b + c + d;
}
函数参数的解构
// 参数是一组有次序的值
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});
函数解构赋值指定参数的默认值
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
用于赋值号左边或函数形参
ES5的方法:
arguments 对象:
function fn(){
console.log(arguments);// 伪数组
}
fn(10, 20, 30, 50, 60);
ES6的方法:
function func( a, b ,...args){ // 把剩余的参数都交给args
console.log(rest);
}
func(10, 20, 30, 50, 60);
function func2(...args){ //args接收所有参数作为一个数组
rest.forEach(function (item) {
console.log(item);
});
}
func2(60, 70, 80, 90);
// 报错
function f(a, ...b, c) {
// ...
}
用于函数实参或者赋值号右边
// 快速将一个数组拆开成一个一个的元素
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:"chenglong",
age:"18",
};
let obj2 = {
email:"[email protected]",
};
let newObj = {...obj1,...obj2}; // 等效于{ name: 'luowowo', age: '18', email: '[email protected]' }
console.log(newObj); //{ name: 'chenglong', age: '18', email: '[email protected]' }
// 4、es6中另一个合并对象的方法
let newObj2 = Object.assign({},obj1,obj2); // 把第二个及第二个以上的参数都合并到第1个上面去。
console.log(newObj2); //{ name: 'chenglong', age: '18', email: '[email protected]' }
基本语法
ES6 允许使用 “箭头”(=>)简化函数的定义。
(参数) => { 函数体 }
1. 形参个数如果为1个,可以省略小括号不写;
// 3、有一个参数 (函数只有一个函数,可以省略()不写
// let fn3 = (a) =>{console.log(a);}
let fn3 = a => console.log(a);
fn3(6)
2. 如果函数体里面只有一个语句,可以省略大括号不写, 并且他会默认返回 => 符号后面的数据。
// let fn1 =() =>{console.log("无参数无返回值");}
let fn1 = () => console.log("无参数无返回值");
fn1();
// 2、无参数有返回值 (函数体只有一句话(并且要返回),{}和return都可以不写
// let fn2 = ()=>{return "无参数有返回值"}
let fn2 = () => "无参数有返回值"
console.log(fn2());
3. 如果函数体有多个语句,则不能省略大括号。
4. 如果函数体只有一个语句,且返回一个对象,建议是,不要写简写的方式。
5. 箭头函数不可以使用 arguments 获取参数列表,可以使用 rest 参数代替。
let fn6 = (...a) =>{
console.log(a); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
}
fn6(1,2,3,4,5,6,7,8,9)
使用场景(回调函数)
// 定时器中的回调函数
setInterval(() => {
console.log("我用了箭头函数");
}, 1000);
// forEach中的回调函数
var arr = [22, 32, 11, 3, 5, 7, 88];
arr.forEach(item => console.log(item));
箭头函数常用的省略
// 当只有一条return语句,{}和return可以一起省略
const getSum = (x, y) => {
return x + y
}
// 可以写为
const getSum = (x, y) => x + y
console.log(getSum(3, 4))
// 当只有一条return语句 并且返回的是一个对象,把这个对象用()包裹起来
const fn = () => ({
a: 1,
})
console.log(fn())
// 形参只有一个,小括号可以省略,其余情况全部要加()
const f2 = (x) => x * 2 // (x)=> {return x *2}
console.log(f2(6))
普通函数中的this:
1. this总是代表它的直接调用者(js的this是执行上下文), 例如 obj.func ,那么func中的this就是obj
2.在默认情况(非严格模式下,未使用 'use strict'),没找到直接调用者,则this指的是 window (约定俗成)
3.在严格模式下,没有直接调用者的函数中的this是 undefined
4.使用call,apply,bind(ES5新增)绑定的,this指的是 绑定的对象
箭头函数中的this:
1.箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),此处指父级作用域,而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this
2.箭头函数中,this指向的固定化,并不是因为箭头函数内部有绑定this的机制,实际原因是箭头函数根本没有自己的this,导致内部的this就是外层代码块的this。
var arrylike = {
"0":"张三",
"1":"李四",
"2":"王五",
"length":3
}
console.log(arrylike);//{0: '张三', 1: '李四', 2: '王五', length: 3}
var ary = Array.from(arrylike);
console.log(ary);//['张三', '李四', '王五']
方法还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。
var arraylike = {
"0":"1",
"1":"2",
"length":2
}
var ary = Array.from(arraylike,item=>item*2) // 2 4
console.log(ary);
用于找出第一符合条件的数组成员,如果没有找到返回undefined
let ary = [{
id: 1,
name: '张三'
},{
id: 2,
name: '李四'
}];
let target = ary.find((item, index) => item.id == 2);
console.log(target);//{id: 2, name: '张三'}
用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
let ary = [10,20,50];
let index = ary.findIndex(item => item> 15);
console.log(index);//1
let ary = ["a","b","c"];
let result = ary.includes('a');
console.log(result);//true
result = ary.includes('e');
console.log(result);//false
ES6 提供了新的数据结构 Set 它类似于数组 但是成员的值都是唯一的 没有重复的值
Set本身是一个构造函数,用来生成 Set 数据结构。
const s = new Set;
Set函数可以接受一个数组作为参数,用来初始化。
const set = new Set([1, 2 ,3 ,4 , 5]);
const s1 = new Set();
console.log(s1.size);// 0
const s2 = new Set(["a","b"]);
console.log(s2.size);// 2
const s3 = new Set(["a","a","b","b"]);
console.log(s3.size);// 2
const ary = [...s3];
console.log(ary);//['a', 'b']
实例方法:
const s4 = new Set();
//向set结构中添加值 使用add方法
s4.add('a').add('b');
console.log(s4.size);//2
//从set结构中删除值,用到的方法是delete
const r1 = s4.delete('a');
console.log(s4.size);//1
console.log(r1);//true
//判断某一个值是否是set数据中的成员 使用has
const r2 = s4.has('b');
console.log(r2);//true
//清空set数据结构中的值 使用clear方法
s4.clear();
console.log(s4.size);//0
遍历set
Set 结构的实例与数组一样,也拥有forEach方法,用于对每个成员执行某种操作,没有返回值
const s5 = new Set (['a','b','c','d','e']);
s5.forEach((value)=>{
console.log(value);
})