var在ES6里面是全局变量
var num = 2;
console.log(num);//打印出来的是2
{var num =3};
console.log(num);//打印出来的是3
let是局部声明
var num = 2;
console.log(num);//打印出来的是2
{
let num = 3;
console.log(num);//打印出来的是3
};
console.log(num);//打印出来的是2
for(var i = 0;i<10;i++){
console.log('循环体内:'+i);
}
console.log('循环体外:'+i);
循环体外面打印的i会变得奇怪,,所以如果用var声明的话在循环体外面用i就会出现问题,使用let声明就可以避免。
for(let i = 0;i<10;i++){
console.log('循环体内:'+i);
}
console.log('循环体外:'+i);
运行之后会发现内部的i没问题,而外面的打印报错:找不到循环体外的变量。
通过两种声明的比较,可以明白let在防止变量被污染上是很有用的,所以要多习惯用let,尽量减少var声明去污染全局空间(Vue的使用也需要注意这点)。
const num = "aaa";
var num = "bbb";
console.log(num);
这段代码在编译的时候就会报错,因为使用const声明的变量是不能改变的。
//ES5写法
let a = 0;
let b = 1;
let c = 2;
//ES6写法
let [d,e,f] = [0,1,2];
console.log(a);
console.log(b);
console.log(c);
let [a,[b,c],d] = [1,[2,3],4];
console.log(a);
console.log(b);
console.log(c);
console.log(d);
等号左右两边的形式要相同,否则会解构失败
let [foo = true] = [];
console.log(foo);//控制台会打印true
了解了默认值之后,下面需要注意的是underfind和null的区别
let [a='aa']=[underfind];
console.log(a)//控制台会打印aa
let [b='bb']=[null];
console.log(b)//控制台会打印null
null就相当于有值,值为null,所以b没有取值,而是直接解构成了null。
let {name,sex} = {name:'LK',sex:'man'};
console.log(name+':'+sex);
let name;
({name}={name:'LK'})
console.log(name);
上面的代码在解构之前就已经声明了变量,所以我们只需要在解构语句的外侧加上圆括号就可以了,如果不加就会出现问题,编译会报错
const [a,b,c,d,e] = "ghost";
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
当我们给方法传入的参数不确定时,我们可以使用对象扩展运算符来作参数:
function foo(...num){
console.log(num[0]);
console.log(num[1]);
console.log(num[2]);
console.log(num[3]);
}
foo(8,8,8);
控制台会打印8,8,8,underfind,说明可以传入多个值,并且就算方法里引用多了也不会报错。
var arr = [0,1,2];
var brr = [3,4,5];
arr.push(...brr);
console.log(arr);//控制台打印0,1,2,3,4,5
rest运算符和对象扩展运算符有很多相似之处,不用特意区分,而且rest运算符也用…(三个点)来表示:
function foo(first,...num){
console.log("first="+first);//0
console.log("num="+num);//1,2,3,4,5
}
foo(0,1,2,3,4,5);
字符串的拼接:
//ES5的写法
let a = "name";
let c = "my "+a+" is LK";
console.log(c);
//ES6的写法
let b = "name";
let d = `my ${b} is LK`;
console.log(d);
对HTML标签支持:
let a = "name";
let c = `my
${a} is LK`
console.log(c);
let a = "LK";
let c = " my name is LK";
document.write(c.includes(a));//true
let a = "LK";
let c = " my name is LK";
document.write(c.startsWith(a));//false
let a = "LK";
let c = " my name is LK";
document.write(c.endsWith(a));//true
document.write('LK'.repeat(5));//会打印5遍LK
//二进制开头是0第二位是大写的B
let num = 0B010101;
console.log(num);//打印21
//八进制开头是0第二位是大写的O
let num = 0O666;
console.log(num);//打印438
可以使用Number.isFinish()来进行数字验证,只要是数字,不论是浮点型还是整形都会返回true,否则就是false
let a = 1;
console.log(Number.isFinite(a));//true
let b = "LK";
console.log(Number.isFinite(b));//false
console.log(Number.isNaN(NaN));//true
let num = 3.14;
console.log(Number.isInteger(num));//false
let num = 3.14;
console.log(Number.parseInt(num));
console.log(Number.parseFloat(num));
console.log(Number.MAX_SAFE_INTEGER);
console.log(Number.MIN_SAFE_INTEGER);
let num = Math.pow(2,53)-1;//num为2的53次方-1
console.log(Number.isSafeInteger(num));//true
//0,1,2是下标,length是长度
let json = {
"0":"aa",
"1":"bb",
"2":"cc",
length:3
}
let arr = Array.from(json);
console.log(arr);
这就是标准的json格式,跟普通的json对比就是在最后多了个length属性,只要是这种特殊的json格式都能使用ES6的语法转变成数组。
let a = Array.of('a','b','c');
console.log(a);
Array.of()方法负责把一堆文本转换成数组
var arr = [1,2,3,4,5,6,7,8,9];
console.log(arr.find(function (index,value,arr){
return index>5;//6
}));
console.log(arr.find(function (index,value,arr){
return index>9;//underfind
}));
控制台打印了6,说明找到了符合条件的值并且返回了,如果找不到则会打印underfind。
fill()也是一个实例方法,作用是把数组进行填充,它接收三个参数,第一个是填充的变量,第二个是开始填充的下标位置,第三个是填充到的具体位置。
let arr = [1,2,3,4,5,6,7,8,9];
arr.fill('a',4,9);
console.log(arr);//结果是[1,2,3,4,"a","a","a","a","a"]
let arr = ['aa','bb','cc'];
for(let item of arr){
console.log(item);
}
let arr = ['aa','bb','cc'];
for(let item of arr.keys()){
console.log(item);
}
let arr = ['aa','bb','cc'];
for(let [index,value] of arr.entries()){
console.log(index+value);
}
entries()实例方式生成的是lterator形式的数组,这种形式的好处就是可以让我们在需要时用next()手动跳转到下一个值:
let arr = ['aa','bb','cc'];
let list = arr.entries();
console.log(list.next().value);
console.log(list.next().value);
console.log(list.next().value);
//ES5写法
function add(a,b){
return a+b;
}
console.log(add(2,3));//5
//ES6写法
var add = (a,b)=>a+b;
console.log(add(1,2));//3
在箭头函数中,方法体内如果是两句话的话,就需要在方法体外面加上{ }括号:
var add = (a,b)=>{
console.log("aaa");
return a+b;
};
console.log(add()1,2));
let json = {
name:'LK',
age:'18'
}
function fun({name,age}){
console.log(name);
console.log(age);
}
fun(json);
let arr = ['a','b','c'];
function fun(a,b,c){
console.log(a,b,c);
}
fun(...arr);
let obj = {
name:'LK',
age:'18'
}
console.log('name' in obj)//true
let arr = [,,];
console.log(0 in arr);//false
let arr1 = ['a','b'];
console.log(0 in arr1);//true
//这里的0指的是数组下标是否为空
let arr = ['aa','cc'];
arr.forEach((value,index)=>{
console.log(value,index);//打印aa 0 cc 2
});
forEach方法的特点是会自动省略空的元素,也就是说直接筛空了
let arr = ['aa',,,'cc'];
arr.filter(x=>{
console.log(x);
});
let arr = ['aa',,,'cc'];
arr.some(x=>{
console.log(x);
});
let arr = ['aa','bb','cc'];
console.log(arr.map(x=>'web'));
map起了一个替换的作用
let arr = ['aa','bb','cc'];
console.log(arr.toString());
let arr = ['aa','bb','cc'];
console.log(arr.join('|'));
let name = "LK";
let age = "18";
let obj = {name,age};
console.log(obj);
有时候我们会在后台取key值,而不是我们前台定义好的,比如我们在后台取了一个key值,这时我们应该用[ ]的形式,进行对象的构建
let key = "name";
let obj = {
[key] = "LK";
}
console.log(obj);
//ES5比较方法
let a = {name:'LK'};
let b = {name:'LK'};
console.log(a.name===b.name);
//ES6比较方法
let c = {name:'LK'};
let d = {name:'LK'};
console.log(Object.is(c.name,d.name));
=== 和 is都可以比较,但是也有区别:
console.log(+0===-0);//true
console.log(NaN===NaN);//false
console.log(Object.is(+0,-0));//false
console.log(Object.is(NaN,NaN));//true
===表示同值相等,is()为严格相等
let a = {name:'LK'};
let b = {age:'18',sex:'man'};
let c = Object.assign(a,b);
console.log(c);
var a = Symbol("ES6");
console.log(a);
console.log(a.toString());
var a = Symnol();
var obj = {
[a] = 'AAA'
}
console.log(obj[a]);//会打印AAA
//不使用Symbol进行保护
var obj = {
name:'LK',
age:'18'
}
for(let item in obj){
console.log(obj[item]);//会打印 LK 18
}
//使用Symbol进行保护
var obj = {
name:'LK'
}
var age = Symbol();
obj[age] = '18';
for(let item in obj){
console.log(obj[item]);//会打印 LK
}
//这样的话别人就看不到age了
Symbol是ES6中引入的一种新的基础数据类型,它的功能类似于一种标识唯一性的ID。通常情况下,我们可以通过调用Symbol()函数来创建一个Symbol实例:
let a = Symbol();
或者,你也可以在调用Symbol()函数时传入一个可选的字符串参数,相当于给你创建的Symbol实例一个描述信息:
let b = Symbol('another symbol');
由于Symbol是一种基础数据类型,所以当我们使用typeof去检查它的类型的时候,它会返回一个属于自己的类型symbol,而不是什么string、object之类的:
let a = Symbol();
console.log(a);//打印Symbol()
另外,我们需要重点记住的一点是:每个Symbol实例都是唯一的。因此,当你比较两个Symbol实例的时候,将总会返回false:
let s1 = Symbol()
let s2 = Symbol('another symbol')
let s3 = Symbol('another symbol')
console.log(s1 === s2);// false
console.log(s2 === s3);// false
我们通常定义或访问对象的属性时都是使用字符串,比如下面的代码:
let obj = {
abc: 123,
"hello": "world"
}
console.log(obj["abc"]);// 123
console.log(obj["hello"]);// 'world'
而Symbol可同样用于对象属性的定义和访问:
const name = Symbol()
const age = Symbol()
let obj = {
[name]: "LK"
}
obj[age] = 18;
console.log(obj[name]);// 'LK'
console.log(obj[age]);// 18
Symbol类型的key是不能通过Object.keys()或者for…in来枚举的,它未被包含在对象自身的属性名集合(property names)之中:
let obj = {
[Symbol('name')]: 'LK',
age: 18,
title: 'Engineer'
}
console.log(Object.keys(obj));// ['age', 'title']
console.log(Object.getOwnPropertyNames(obj));// ['age', 'title']
for (let p in obj) {
console.log(p) // 分别会输出:'age' 和 'title'
}
//也正因为这样一个特性,当使用JSON.stringify()将对象转换成JSON字符串的时候,Symbol属性也会被排除在输出内容之外:
console.log(JSON.stringify(obj)); // {"age":18,"title":"Engineer"}
//因此可以利用这一特点来更好的设计我们的数据对象
不过还是会有一些专门针对Symbol的API,比如Object.getOwnPropertySymbols()或Reflect.ownKeys():
let obj = {
[Symbol('name')]: 'LK',
age: 18,
title: 'Engineer'
}
// 使用Object的API
console.log(Object.getOwnPropertySymbols(obj) );// [Symbol(name)]
// 使用新增的反射API
console.log(Reflect.ownKeys(obj)); // [Symbol(name), 'age', 'title']
//新建一个index.js文件
const PASSWORD = Symbol()
class Login {
constructor(username, password) {
this.username = username
this[PASSWORD] = password
}
checkPassword(pwd) {
return this[PASSWORD] === pwd
}
}
export default Login
//然后再建一个index2.js文件
import Login from './index'
const login = new Login('LK', '000000')
console.log(login.checkPassword('000000'));// true
console.log(login.PASSWORD);
console.log(login[PASSWORD]);
console.log(login["PASSWORD"]);
以上代码可以看出Symbol常量PASSWORD被定义在index.js所在的模块中,外面的模块获取不到这个Symbol,也不可能再创建一个一模一样的Symbol出来,这是因为Symbol是唯一的,所以这个PASSWORD的Symbol只能被限制在index.js内部使用,使用它来定义的类属性是没有办法被模块外访问到的,达到了一个私有化的效果
let a = Symbol.for('global_symbol_1') //注册一个全局Symbol
let b = Symbol.for('global_symbol_1') //获取全局Symbol
console.log(a===b);// true
这样就可以在别的模块也能使用同一个Symbol了
Set和Array的区别是Set不允许内部有重复的值,如果有的话就只显示一个,也就是去重复,Set不是数组:
let setArr = new Set(['aa','bb','cc','cc']);
console.log(setArr);//打印aa,bb,cc
let setArr = new Set(['aa','bb','cc']);
setArr.add('dd');
console.log(setArr);//打印aa,bb,cc,dd
let setArr = new Set(['aa','bb','cc']);
setArr.delete('aa');
console.log(setArr);//打印bb,cc
let setArr = new Set(['aa','bb','cc']);
console.log(setArr.has('cc'));//打印true
let setArr = new Set(['aa','bb','cc']);
setArr.clear();
console.log(setArr);
let setArr = new Set(['aa','bb','cc']);
for(let item of setArr){
console.log(item);
}
let weakObj = new WeakSet();
let obj = {
name:'LK',
age:'18'
} ;
weakObj.add(obj);//只能通过add()插入值,否则会报错
console.log(weakObj);
let weakObj = new WeakSet();
let obj = {
name:'LK',
age:'18'
} ;
let obj1 = obj;
weakObj.add(obj);
weakObj.add(obj1);
console.log(weakObj);
//内存空间相同的话只会插入一个对象
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map);
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map.get("b"));
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map.delete("b"));
//根据key删除值
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map.size);
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map.has('a'));
let obj = {
name:"LK",
age:'18'
};
let map = new Map();
map.set("a",obj);
map.set("b",1);
console.log(map.clear);
const person = {name: 'lk', age: 2000}
const personProxy = new Proxy(person, {
get(target, key) {
//get是用来得到某对象的值而进行预处理的方法
console.log('someone ask for', target, key);
return target[key].toUpperCase();
},
set(target, key, value) {
//set是用来改变属性值而进行预处理的方法
if (typeof value === 'string'){
target[key] = value.trim();
}
}
});
personProxy.name = 'codecasts';
console.log(personProxy)
apply的作用是在方法体是一个匿名函数的时候调用内部的方法
let target = function () {
return 'hello';
};
var handler = {
//apply里的内容会优先运行
apply(target,ctx,args){
console.log('apply starts' );
return Reflect.apply(...arguments);
}
}
var pro = new Proxy(target,handler);
console.log(pro());
promise适合执行多步操作
let state = 1;
function a(resolve, reject) {
console.log('First starts');
if (state == 1) {
resolve('First success');
} else {
reject('First file');
}
}
function b(resolve, reject) {
console.log('Second starts');
if (state == 1) {
resolve('Second success');
} else {
reject('Second file');
}
}
function c(resolve, reject) {
console.log('Third starts');
if (state == 1) {
resolve('Third ssuccess');
} else {
reject('Third sfile');
}
}
new Promise(a).then(function (val) {
console.log(val);
return new Promise(b);
}).then(function (val) {
console.log(val);
return new Promise(c);
}).then(function (val) {
console.log(val);
return val;
});
class Coder{
name(val){
console.log(val);
return val;
}
skill(val){
console.log(this.name("aa")+":"+"skill:"+val);
}
}
let guo = new Coder();
guo.skill('bb');
class Coder{
constructor(a,b){
this.a = a;
this.b = b;
}
add(){
return this.a+this.b;
}
}
let guo = new Coder(1,2);
console.log(guo.add());
上面的方法使用constructor来约定传递参数,然后使用add方法将参数相加。
class Coder{
constructor(a,b){
this.a = a;
this.b = b;
}
add(){
return this.a+this.b;
}
}
let guo = new Coder(1,2);
console.log(guo.add());
class Htmlel extends Coder{
}
let guo = new Htmlel();
//新建一个js文件,在里面输出一个模块变量
export var a = '123'
//然后再建一个js文件,在里面用import引入
import {a} from './a.js'
console.log(a);
var a = '123';
var b = '456';
var c = '789';
export{a,b,c}
export function add(a,b){
return a+b
}
当我们不想暴露模块内的变量名,而给模块起一个更语义化的名字,可以用as进行操作:
var a = '123';
var b = '456';
var c = '789';
export{
a as x,
b as y,
c as z
}
export default等于是一个默认的入口,它于export有些不同,而一个文件里面只能有一个export default
//导出
export var a = '123';
//导入
import str from './xxxx';