1. let、const,用法和var一样
1. 作用域不同
function fn(){
if(true){
console.log(a)
}else{
var a
}
}
fn() //undefined,因为var a变量提升了
var除了在函数里是局部变量,在其它地方声明都是全局变量。
用let来声明变量,只在自己所在的代码块内有效。
//例1
{
let a = 10;
var b = 1;
{
console.log(a)
//a is not defined,a既不会跑到外面,也不会到里面来
}
}
a // a is not defined.
b // 1
//例2
for (let i = 0; i < 3; i++) {
let i = 'abc'; //这个i和上面的数字i不互相影响
console.log(i);
}
// abc
// abc
// abc
- const
声明一个变量只能赋值一次,且必须在声明的时候赋值const a = 1 a = 2 //报错 const b; //报错
3. let、const不会变量提升!
- 面试题1
var a = 1
function fn(){
console.log(a)
}
a = 2
fn() //2
- 面试题2
for(var i=0;i
不管点第几个都会输出liTags.length,可以改成下面这样
for(let i=0;i
这样点第几个就输出几
2. 解构赋值
-
交换两个变量的值
let a = 1; let b = 2; //这里必须加分号,下面的方括号会自动往前提一行 [a,b] = [b,a]
-
对象
//es5 let options = response.options let method = options.method; //es6 let {method} = options //es6,下面一行等于上面es5的两行 let {options:{method}} = response;
-
若是用在函数里:
function name1(response){ let {human:{name2}} = response; console.log(name2) } //简化为下面,直接把这个当参数可以省略response function({human:{name2}}){}
奇异写法:
function name1(response){ let {human: man='default'} = response; console.log(man) //等于重命名human,man === response.human //default是默认值 }
-
默认参数
let [a=1,b=2] = [23] //前面写的是默认值,若后面没有则用默认值 // a === 23, b === 2 let [a, ,b] = [1,2,3] //a === 1, b === 3
3. 对象里的函数
//es5
object{
go: function(){
}
}
//es6
object{
go(){
}
}
4. ...语法(部分移动端不支持)
function sum(...numbers){console.log('numbers',numbers)}
sum(1,2,3,4)
//[1,2,3,4],numbers是一个真正的数组
function sum(message,...numbers){console.log('numbers',numbers)}
sum('hello',1,2,3,4)
//[1,2,3,4],numbers代表除第一个外的所有参数
//三个点的那一项必须在最后一位
- 拷贝(只有根属性是深拷贝)
var a = {name: 'pyz'};
var b = {c1:1, c2:2 ,c3:3}
var c ={...a,...b} //相当于存了a和b里的所有属性
//c === {name: 'pyz', c1: 1, c2: 2, c3: 3}
//若不写...,则相当于给c里存了两个对象
c = {a,b}
//合并a和b
var a = {apple: 1,ban: 2}
var b = {ban: 1,curry: 3}
var c = {...a,...b}
这个语法能把伪数组变为真数组
function a() {
let args = [...arguments]
console.log(args)
}
还能进行展开操作
let array = [1,2,3,4,5];
let [,,...array2] = array;
array2 //[3,4,5]
let array3 = [0 , ...array , 6];
array3 //[0,1,2,3,4,5,6]
5. 将伪数组变为数组
let args = Array.from(arguments)
//把伪数组变成真数组,还可以用[...arguments]
Array.from({length:4})
//[undefined,undefined,undefined,undefined]
- 面试题
function x(n,fill){
let a = Array.from({length: n})
return a.map(v=>fill)
}
x(6,6)
//[6,6,6,6,6,6]
还可以用fill
function x(n,fill){
return Array.from({length: n}).fill(fill)
}
//把数组所有位置都替换成6
let a = [1,2,3]
a.fill(7,1)
//把1后面的替换成1
6. 新字符串
这个字符串支持回车,之前的不能回车,结果包含4个回车。
- 还可以插值
- 函数后接新字符串
let name = 'p'
let person = 'y'
function fn(){
console.log(arguments)
}
fn`${name}可以${person}`
这个功能在react的style-component库用到了!
7. Symbol
用来创建独一无二的值
let race = {
神族: Symbol() , 人族: Symbol(), 虫族: Symbol()
}
race.神族 === race.人族 //false
8. 迭代器和发布器
- 迭代器(es5)
function createIterator(items) {
var i = 0;
return {
next: function() {
var done = (i >= items.length);
var value = !done ? items[i++] : undefined;
return {
done: done,
value: value
};
}
};
}
var iterator = createIterator([1, 2, 3]);
console.log(iterator.next()); // "{ value: 1, done: false }"
console.log(iterator.next()); // "{ value: 2, done: false }"
console.log(iterator.next()); // "{ value: 3, done: false }"
console.log(iterator.next()); // "{ value: undefined, done: true }"
- 生成器(es6,是迭代器的语法糖)
function * 生成器(){
let version = 0;
while(true){
version += 1
yield version
}
}
let a = 生成器()
a.next() //{value: 1,done: false}
a.next() //{value: 2,done: false}
- for ... of
数组可以迭代,对象不行,就因为没有Symbol.iterator
let a = [1,2,3]
a[Symbol.iterator] //f()...
let o = {1:'a',2:'b'}
o[Symbol.iterator] //undefined
若自己给对象添加Symbol.iterator属性,则对象也可以迭代,如下
o[Symbol.iterator] = function *(){
let keys = Object.keys(object)
for(let i=0;i
for ... of ...的用法
let a = [1,2,3]
for(let o of a){
console.log(o)
}
//1 2 3
9. 对象
- Object.create(null)
let a = Object.create(null)
//创建一个新对象,里面没有Object.prototype
若要使它指向Object的原型,可以想下面这样
let a = Object.create(Object.prototype)
这样就等价于a = {}
和a = new Object()
参数里写的东西会放进a的__proto__里
- 对象的属性可以是变量
var name = 'a'
let o = {[name]:1}
//对象属性可以这样引用变量
var n = 1
let o = {
[n*2]:123
}
o //{2:123}
- 新对象!可以自己控制对象读和写的操作
o = {
_age: 18,
get age(){return o._age},
set age(value){ if(value<100){o._age = value}}
}
像下面这样写,这样可以使a==1&&a==2&&a==3
为true
var i=0
Object.defineProperty(window,'a',{
get(){
i += 1
return i
}
})
a==1&&a==2&&a==3
若只给get()属性,则这个对象是只读的
o ={
get name(){return '只读'}
}
o.name = 1
console.log(o.name) //'只读',是无法改变的
- Object.defineProperty()
这个API可以将对象改造为新对象
let a = {a:'a',b:'b'}
Object.defineProperty(a,'x',{
get(){},
set(value){}
})
还可以定义对象为只读
Object.defineProperty(a,'name',{
writeable: false, //这个属性是只读的
value: 'pyz',
configurable: false
//无法再对这个对象里面的属性更改
enumerable: false //遍历时不会显示出来
})
Object.getPrototypeOf(a)
获取一个对象的原型,相当于a.__proto__
Object.defineProperties()
可以一次性定义多个
Object.defineProperty(a,{
'name': {
writeable: false,
value: 'pyz',
configurable: false
//无法再对这个对象里面的属性更改
enumerable: false //遍历时不会显示出来
},
'age':{
value: 18
}
})
vue的双向绑定就是靠这个API实现的!
Object.keys(a)
这样会把a的属性作为一个数组返回Object.entries(a)
这样是把a的每个属性和值放在一个数组里,然后返回一个大数组里有很多小数组Object.freeze()
let o = {a:1}
let o2 = Object.freeze(o)
这样o2的所有属性则不能被改动了
10. Symbol可以当作对象的key
10. 浅拷贝
- Object.assign
let o = {a:'a',b:'b',c:'c'}
let object = Object.assign({},o)
//这样o上所有属性就拷贝到object上了
//仅有根属性是深拷贝
- ...
let o = {a:'a',b:'b',c:'c'}
let object = {...o}
//和上面Object.assign一样
11. ES6模块化
- index.html
//这里一定要写type=module
- main.js
import module1 from './1.js'
import {say} from './2.js'
setTimeout(function(){
module1()
},2000)
setTimeout(function(){
module2()
},3000)
- 1.js
let name = 'pyz'
let module1 = function(){
console.log('name1:',name);
}
export default module1
用 export default 的方法导出,你在其他文件引用时就可以自定义名字
- 2.js
let name = 'jpj'
let say = function(){
console.log('name2:',name);
}
export {name,say}
export default say
这样导出时,引用可以import x,{name,say} from './2.js'
若导出的局部变量名重复了,可以如下这样
import {name as name1} from './1.js'
import {name as name2} from './2.js'
- import * as all from './1.js'
导入所有的,名字是all
12. 若浏览器不支持import语法,使用parcel
npm init -y
npm install -g parcel-bundler
parcel index.html
- 访问给出的地址,parcel就已经帮你把es6新语法转化为IE支持的语法了
13. 类
class Person{
constructor(name,age){ //自有属性
this.name = name;
this.age = age;
} //不用写逗号
walk(){}
}
类可以继承
class Animal{
constructor(species){
this.species = species
this._race = '动物'
}
say(){
console.log('我是动物')
}
get race(){ //读取race值
return this._race
}
static die(){
//静态方法只能通过Animal.die()访问到
console.log('灭绝')
}
set race(value){
//设置race值,如果没有set则不能改这个值
//set里还可以加if(),来限制各种条件
this._race = value
}
}
class Person extends Animal{ //继承原型
constructor(species,name,age){
super(species) //继承自有属性
this.name = name;
this.age = age;
} //不用写逗号
walk(){}
say(){
super.say() //'我是动物'
console.log('人')
}
}
14. Promise
15. async/await
function takeLongTime() {
return new Promise(resolve => {
setTimeout(() => resolve(1), 1000);
});
}
async function test() {
let v = await takeLongTime();
console.log(v);
console.log(2)
}
test();
async/await必须和promise结合使用
16. Set
Set是一个对象,会自动去重
new Set([1,2,3,4,5,5,5,5])
//{1,2,3,4,5}
17. Map
Map也是对象,它可以把对象当作key,还可以用for...of...迭代!
let myMap = new Map()
let key = {}
let value = 1
myMap.set(key,value) //key可以是对象
myMap.get(key) //获得value
for(let i of myMap){
console.log(i) //会打印出key和value
}
for(let i of myMap.values){
console.log(i) ////会打印出value
}
for(let i of myMap.keys){
console.log(i) ////会打印出value
}
for(let i of myMap.entries){
console.log(i) ////会打印出value
}
myMap.forEach((value,key)=>{
})
18. weakSet
弱引用,没法读取对象里所有的值
19. weakMap
弱引用
20. 新API
- fill
let a = ['a','b','c']
a.fill(3) //[3,3,3]
a.fill(2,1) //[3,2,2,]
- find
a.find(item=>item===2) //2
find查到第一个就返回,用filter可以查找所有
- findIndex
let a= [3,3,3,2]
a.findIndex(item=>item===2) //3
- entries/keys/value
可迭代对象
let a = [1,2,3]
let aa = a.values
a.next.value //1
a.next.value //2
a.next.value //3
- includs
let a = 'apple'
a.includes('ap') //true
a.includes('b') //false
a.indexof('a') >= 0
也是一样的效果
a.search('a') >= 0
也是一样的效果,但search可以用正则,a.search(/a/) >= 0
- repeat
let s = 'a'
s.repeat(2) //'aa'
- Number.EPSILON
JS可做到的最小误差
let i=0
while(Math.abs(i-1)
- Number.isInteger
Number.isInteger(1) //true
- Number.isFinite
判断是不是有限数字 - Number.isNaN
Number.isNaN(NaN) //true
判断是不是NaN,还有一个老的是window.isNaN