var
,可同时声明多个变量,可在声明时赋初始值。let 可用于解决闭包问题。for(var i = 0; i < 3; i++){ }
,由于 var 没有块级作用域,声明的 i 在全局中,循环结束后 i 都会变成 3(执行循环中的函数时,i 已经变成 3 了)。用 let 声明,相当于在三个代码块里声明了三个 i ,它们是互不影响的。
var
、let
ES6 允许按照一定模式从数组和对象中提取值,对变量进行赋值。这称为解构赋值
const nums = [1,2,3,4];
let [one, two, three, four] = nums;
console.log(one); //1
console.log(two); //2
console.log(three); //3
console.log(four); //4
const ppp = {
name: 'ppp',
num: '131509',
game: function(){
console.log("fps...");
}
};
let {
name,num,game} = ppp;
console.log(name); //ppp
console.log(num); //131509
game(); //fps...
ES6引入新的声明字符串的方式【 ` ` 】反引号
let num1 = `12123`;
let num2 = `131509`;
let num = `${
num1}${
num2}`;
console.log(num); //12123131509
ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
let num1 = '23';
let num2 = '38';
let sum = function(){
console.log(num1+num2);
}
const math = {
num1,
num2,
sum,
}
console.log(math);
let fn = function(){ }
----> let fn = () =>{ }
let box = document.getElementsByClassName('box')[0];
//绑定事件
box.addEventListener("click", function(){
//保存this的值
//let _this = this;
setTimeout(() => {
//_this.style.backgroundColor = 'pink';
this.style.backgroundColor = 'pink';
},2000);
});
ES6允许给函数参数赋初始值
function connect({
host,username,password}){
console.log(host);
console.log(username);
console.log(password);
}
connect({
host:'localhost',
username:'root',
password:'root'
})
ES6 引入 rest 参数,用于获取函数的实参,用来代替 arguments
function date(){
console.log(arguments); //结果是一个类数组
}
date('1','2','3');
function date(...args){
console.log(args); //结果是一个数组
}
date('1','2','3');
function date(a,b,...args){
console.log(a);
console.log(b);
console.log(args); //3,4,5,6 会给到 args
}
date(1,2,3,4,5,6);
【…】 扩展运算符能将【数组】转换为逗号分隔的参数序列。
const date=[1,2,3];
function fn(){
console.log(arguments);
}
fn(date); //结果中只有一个值(数组)。
fn(...date); //会将数组转换,结果中有三个值。
【应用】
const num1 = [1,2,3];
const num2 = [4,5,6];
const sum = [...num1,...num2];
const num = [1,2,3,7];
const numC = [...num];
const divs = document.querySelectorAll('div');
const divArr = [...divs];
ES6 引入了一种新的原始数据类型 Symbol,表示独一无二的值,是 JavaScript 的第七种数据类型,是一种类似字符串的数据类型。
symbol 详情指路 阮一峰的ES6
【 创建】
let s1 = Symbol('张三');
let s2 = Symbol('张三');
console.log(s1 === s2); //false
let s3 = Symbol.for('张三');
let s4 = Symbol.for('张三');
console.log(s3 === s4); //true
【使用】
symbol 是一个独一无二的值,可给对象添加属性和方法
//想向对象中添加方法
let game = {
}
//1. 下面的方法不好,无法确定对象中是否已有同样命名的方法
//game.up = function(){
//}
//2. 使用 Symbol 添加
// 1) 声明一个对象
let methods = {
up: Symbol(),
down:Symbol()
};
// 2) 添加方法
game[methods.up] = function(){
console.log("正在上升");
}
game[methods.down] = function(){
console.log("正在下降");
}
//在对象中添加 Symbol 类型的方法
let card = {
name: '狼人杀',
[Symbol('say')]: function(){
console.log("发言中...");
},
[Symbol('kill')]: function(){
console.log("选择要杀死的玩家...");
}
}
card[Symbol('say')](); //报错
//因为Symbol('say')生成的标识不是唯一的,所以定义的在 card 里面的[Symbol('say')]是无法调用的,除非把Symbol('say')放块外面定义,并用变量保存。
let card = {
name: '狼人杀',
[Symbol.for('say')]: function(){
console.log("发言中...");
},
[Symbol.for('kill')]: function(){
console.log("选择要杀死的玩家...");
}
}
card[Symbol.for('say')](); //发言中....
//Symbol.for('say')产生的标识是唯一的,所以可以调用定义在 card 里面的[Symbol.for('say')]方法。
内直值 | |
---|---|
Symbol.hasInstance | 当其他对象使用 instanceof 运算符, 判断是否为该对象的实例时,会调用这个方法 |
Symbol.isConcatSpreadable | 对象的 Symbol.isConcatSpreadable 属性等于的是一个布尔值,表示该对象用于 Array.prototype.conct() 时,是否可以展开 |
Symbol.unscopables | 该对象指定了使用 with 关键字时,哪些属性会被 with 环境排除 |
Symbol.match | 当执行 str,match(myObject) 时,如果该属性存在,会调用它,返回该方法的返回值 |
Symbol.replace | 当该对象被 str.replace(myObject) 方法调用时,会返回该方法的返回值 |
Symbol.search | 当该对象被 str.search(myObiect)方法调用时,会返回该方法的返回值 |
Symbol.split | 当该对象被 str.split(myObiect)方法调用时,会返回该方法的返回值 |
Symbol.iterator | 对象进行 for…of 循环时,会调用 Symbol.iterator 方法,返回该对象的默认遍历器 |
Symbol.toPrimitive | 该对象被转为原始类型的值时,会调用这个方法,返回该对象对应的原始类型值 |
Symbol.toStringTag | 在该对象上面调用 toString 方法时,返回该方法的返回值 |
Symbol.species | 创建衍生对象时,会使用该属性 |
迭代器 (Iterator) 是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署 Iterator 接口,就可以完成遍历操作。
const xiyou = ['tang','sun','zhu','sa']
//使用 for...of 遍历数组,得到的是键值
for(let v of xiyou){
console.log(v); //tang sun zhu sa
}
//使用 for...in 遍历,得到的是键名
for(let k in xiyou){
console.log(k); //0 1 2 3
}
const xiyou = ['tang','sun','zhu','sa'];
let iterator = xiyou[Symbol.iterator]();
//调用对象的 next 方法
console.log(iterator.next()); //{value: "tang", done: false}
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next());
console.log(iterator.next()); //{value: undefined, done: true}
//done 的值为 true 表示遍历完成
生成器函数是 ES6 提供的一种异步编程解决方案,语法行为与传统函数完全不同, 可以用来进行异步编程
//声明
function * gen(){
console.log("hello");
}
let iterator = fn();
console.log(iterator); //可以看到它是一个迭代器对象
iterator.next(); //想调用这个函数,需借助迭代器中的 next 方法
//yield 函数代码分隔符,将代码分割成一块一块的
function * gen(){
console.log(111);
yield '1';
console.log(222);
yield '2';
console.log(333);
yield '3';
console.log(444)
}
let iterator = gen();
iterator.next(); //next 只执行第一个代码块的内容
function * gen(arg){
console.log(arg); //AAA
let one = yield 111;
console.log(one); //BBB
let two = yield 222;
console.log(two); //CCC
let three = yield 333;
console.log(three); //DDD
}
let iterator = gen('AAA'); //正常传参
iterator.next('');
iterator.next('BBB'); //传入第一个yield中
iterator.next('CCC'); //传入第二个yield中
iterator.next('DDD'); //传入第三个yield中
【实例-1】
需求:1s 后控制台输出 111,2s 后控制台输出 222,3s 后控制台输出 333。
//定时器,产生回调地狱
setTimeout(() => {
console.log(111);
setTimeout(() => {
console.log(222);
setTimeout(() => {
console.log(333)
},1000)
},1000)
},1000)
//生成器函数
function one(){
setTimeout(() => {
console.log(111);
iterator.next();
},1000)
}
function two(){
setTimeout(() => {
console.log(222);
iterator.next();
},1000)
}
function three(){
setTimeout(() => {
console.log(333);
iterator.next();
},1000)
}
function * gen() {
yield one();
yield two();
yield three();
}
//调用生成器函数
let iterator = gen();
iterator.next();
【实例-2】
需求:模拟获取 用户数据、订单数据、商品数据(一步步获取)
function getUsers(){
setTimeout(() => {
let data = '用户数据'
//调用 next 语句,将数据传入
//此处是第二次调用,参数传到第一个 yield 中
iterator.next(data);
}, 1000)
}
function getOrders(){
setTimeout(() => {
let data = '订单数据'
iterator.next(data);
},1000)
}
function getGoods(){
setTimeout(() => {
let data = '商品数据'
iterator.next(data);
},1000)
}
function * gen(){
let user = yield getUsers();
console.log(user);
let order = yield getOrders();
console.log(order);
let good = yield getGoods();
console.log(good);
}
let iterator = gen();
iterator.next();
Promise 是ES6 引入的异步编程的新解决方案,语法上 Promise 是一个构造函数,用来封装异步操作并可以获取其成功或失败的结果。解决回调地狱的问题。
关于回调函数
//实例化 Promise 对象
const p = new Promise(function(resolve, reject){
setTimeout(function(){
// resolve 调 then 的第一个回调函数
let data = '数据库中的数据';
resolve(data);
// reject 调 then 的第二个回调函数
let err = '读取失败';
reject(err);
}, 1000);
});
//调用 promise 对象的 then 方法
p.then(function(value){
console.log(value);
}, function(reason){
console.error(reason); //控制台输出有红叉是因为'console.error'
});
//1. 引入 fs 模块( fs 是 node 自带的核心模块)
const fs = require('fs');
//2. 调用方法读取文件
//第一个参数是文件路径,第二个参数是回调函数
//err 错误对象,data是读取出的结果,是一个Buffer格式的
fs.readFile('D:/Web/wenjian.md',(err, data)=>{
//如果失败,则抛出错误
if(err) throw err;
//如果没有错误,则输出内容
console.log(data.toString());
});
//3. 使用 Promise 封装
const p = new Promise(function(resolve,reject){
fs.readFile('D:/Web/wenjian.md',(err, data)=>{
//如果失败
if(err) reject(err);
//如果成功
resolve(date);
});
});
p.then(function(value){
console.log(value);
},function(reason){
console.log("读取失败")
})
使用原生 AJAX 向一个地址发送一个请求
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("Get","https://api.apiopen.top/getJoke");
//3. 发送
xhr.send();
//4. 绑定事件,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态码 200-299
if(xhr.status >= 200 && xhr.status < 300){
//成功
console.log(xhr.response);
}else{
//如果失败
console.log(xhr.status);
}
}
}
Promise 封装
const p = new Promise((resolve, reject)=> {
//1. 创建对象
const xhr = new XMLHttpRequest();
//2. 初始化
xhr.open("Get","https://api.apiopen.top/getJoke");
//3. 发送
xhr.send();
//4. 绑定事件,处理响应结果
xhr.onreadystatechange = function(){
//判断
if(xhr.readyState === 4){
//判断响应状态码 200-299
if(xhr.status >= 200 && xhr.status < 300){
//成功
resolve(xhr.response);
}else{
//如果失败
reject(xhr.status);
}
}
}
})
//指定回调
p.then(function(value){
console.log(value);
},function(reason){
console.error(reason);
})
对于异步成功和失败的结果,处理方式不同。【原来是在回调函数中处理】,【现在是在异步任务的后面,通过 then 方法来指定回调。】
指定成功和失败的回调
//创建Promise对象
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
resolve('shuju');
},1000)
});
//调用 then 方法, then 方法的返回结果是 Promise 对象, 对象状态由回调函数的执行结果来决定。
const result = p.then(value =>{
console.log(value);
//1. 如果回调函数中返回的结果是 非Promise 类型的属性,状态为成功,返回值为对象的成功的值(PromiseResult:"ok")。
//return "ok";
//2. 返回的结果是 promise 对象,此处成功的值,就是 then 方法成功返回的值(PromiseResult:"ok"),如果此处promise失败(PromiseResult:"ok"),reject中的值
//return new Promise((resolve,reject)=>{
//resolve('ok');
//reject('error');
//});
//3. 抛出错误
//throw new Error('出错啦!');
},reason=>{
console.log(reason);
});
console.log(result); //then 方法的返回结果是 Promise 对象
【链式调用】then 方法的返回结果也是一个 Promise 对象
p.then(value=>{
}).then(value=>{
});
指定失败的回调
const p = new Promise((resolve,reject)=>{
setTimeout(()=>{
reject("出错了!!");
},1000)
});
p.catch(function(reason){
console.warn(reason);
})
ES6提供了新的数据结构 Set (集合)。类似于数组,但成员的值都是唯一的。
//声明 set
let s = new Set();
let s2 = new Set([1,2,3,0,0])
console.log(s2); //1, 2, 3, 0
//元素个数
console.log(s2.size); //4
//添加新元素
s2.add(5);
console.log(s2); //1, 2, 3, 0, 5
//删除元素
s2.delete(0);
console.log(s2); //1, 2, 3, 5
//检测
console.log(s2.has(2)); //true
//清空
s2.clear();
console.log(s2);
【应用】
let arr = [1,2,5,6,6,7,5];
//1.数组去重
// let result = [...new Set(arr)];
// console.log(result);
//2.交集
let arr2 = [4,5,6,5,6]
let result = [...new Set(arr)].filter(item =>new Set(arr2).has(item));
console.log(result);
//3.并集
let union = [...new Set([...arr,...arr2])];
console.log(union);
//4.差集
let diff = [...new Set(arr)].filter(item => !(new Set(arr2).has(item)));
console.log(diff);
ES6 提供了 Map 数据结构。类似于对象,也是键值对的集合。【键的范围不限于字符串,各种类型的值(包括对象)多可以当作键】
//声明 Map
let m = new Map();
//添加元素
m.set('name','张三');
m.set('play',function(){
console.log("playing....");
});
let key = {
from : 'sky'
};
m.set(key, ['beijing', 'shanghai']);
console.log(m);
//size
console.log(m.size);
//删除
m.delete('name');
console.log(m);
//获取
console.log(m.get('play'));
console.log(m.get(key));
//遍历
for(let v of m){
console.log(v);
}
let b = 0b1010; //二进制
let o = 0o12; //八进制
let d = 100; //十进制
let x = 0xff; //十六进制
console.log(b,o,d,x); //10 10 100 255
console.log(Number.isFinite(100)); //true
console.log(Number.isFinite(100/0)); //false
console.log(Number.isFinite(Infinity)); //false
console.log(Number.isNaN(NaN)); //true
console.log(NaN === NaN); //false
console.log(Number.parseInt('123456iii')); //123456
console.log(Number.parseFloat('3.1415926pai')); //3.1415926
console.log(Number.isInteger(3.2)); //false
console.log(Math.trunc(3.2)); //3
console.log(Math.sign(100)); //1
console.log(Math.sign(-100)); //-1
console.log(Math.sign(0)); //0
console.log((0.1 + 0.2) === 0.3); //false
//使用 Number.EPSILON 封装函数
function equal(a,b){
if(Math.abs(a-b) < Number.EPSILON){
return true;
}else{
return false;
}
}
console.log(equal((0.1+0.2),0.3)) //true
console.log(Object.is(+0, -0)) // false
console.log(Object.is(NaN, NaN)) // true
const target = {
a: 1 };
const source1 = {
b: 2 };
const source2 = {
c: 3 };
Object.assign(target, source1, source2);
console.log(target); // {a:1, b:2, c:3}
1)Object.assign()方法的第一个参数是目标对象,后面的参数都是源对象。
2)如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
3)如果只有一个参数,Object.assign()会直接返回该参数。如果该参数不是对象,则会先转成对象,然后返回。
4)由于undefined和null无法转成对象,所以如果它们作为参数,就会报错。【如果非对象参数出现在源对象的位置(即非首参数),那么处理规则有所不同。首先,这些参数都会转成对象,如果无法转成对象,就会跳过。这意味着,如果undefined和null不在首参数,就不会报错。】
【内容不是很全,后续会不定时的来补充修改完善的,感谢阅读。~(~ ̄▽ ̄)~】