JS对象
JSON.stringify(obj/arr) //js对象或数组转换为json对象或数组
JSON.parse(json) //json对象或数组转换为js对象或数组
var obj = {name: 'Tom'}
obj = JSON.stringify(obj)
console.log(obj); //{"name":"Tom"} String
obj = JSON.parse(obj)
console.log(obj); //{ name: 'Tom' } Object
JS数组
Array.prototype.indexOf(value) //得到值在数组中的第一个索引
Array.prototype.LastIndexOf(value) //得到值在数组中的最后一个索引
Array.prototype.forEach(function(item,index){}) //遍历数组
Array.prototype.map(function(item,index){ return item+1 }) //遍历数组返回一个新的数组,返回加工之后的值
//item每个+1
Array.prototype.filter(function(item,index){}) //遍历过滤出一个新的子数组,返回条件为true的值
JS函数
区别bind()与call()和aplly()?
- 都能指定函数中的this
- call和apply是立即调用函数
- bind是将函数返回
- 传入参数的形式
Function.prototype.bind(obj) //将函数内的this绑定为obj,并将函数返回
foo.call(obj,33,44)
foo.apply(obj,[33,44])
foo.bind(obj,33,44)() //得到返回的函数,需要再后面加括号才能立即调用
//bind传参方式和call一样
setTimeout(function(){
console.log(this)
}.bind(obj),1000) //这里的this指向obj
let关键字
特点: 在块级作用域内有效 不能重复声明 不会预处理,不存在提升
应用: 循环遍历加监听
console.log(i) //报错
let i = 1
let i = 1 //报错
const关键字
作用:定义一个常量
特点: 不能修改 其他特点同let
应用: 保存不用改变的数据
变量的解构 赋值
从对象或数组中提取数据,并赋值给变量(多个)
let obj = {name:'Tom' , age:12}
let {name , age} = obj //等于赋obj.name和obj.age中的值
let arr = [1,3,5,'abc',true]
let [a,b,c,d,e] = arr //根据下标来给值
let[,,a,b] = arr //a==5,b=='abc
function foo({name,age}){ // let {name,age} = obj
console,log(name , age)
}
foo(obj)
模板字符串
简化字符串的拼接 模板字符串必须用到``包含 变化的部分用${xxx}定义
let obj ={name:'Tom' ,age:12}
let str = `我的名字叫:${obj.name},我的年龄是:${obj.age}`
简化的对象写法
省略同名的属性值 省略同名的function
let name = 'Tom'
let age =39
let obj = {
name:name,
age:age,
getName: function(){
return this.name
}
}
//在es6中
let obj = { //同名的属性可以省略不写
name,
age,
getName(){ //可以省略函数的:function
return this.name
}
}
箭头函数详解
作用:定义匿名函数
基本语法: 没有参数:()=> console.log('xxxx) 一个参数:i=>i+2 大于一个参数:(i,j)=> i+j 函数体不用大括号:默认返回结果 函数体如果有多个语句,需要用{}包围,若有需要返回的值,需要手动返回
使用场景:多用于定义回调函数
箭头函数的特点:
1.简洁
2.箭头函数没有自己的this,箭头函数的this不是调用时候决定的,而是在定义的时候处在的对象就是他的this
3.扩展理解:箭头函数的this看外层是否有函数,如果有,外层函数的this就是内部箭头函数的this,如果没有则this是window
let fun = ()=> console.log('xxx')
fun() //xxx
let fun = (i,j)=> console.log(i+j)
fun(1,2) //3
let fun = (x,y) => {
x+y //undefined
return x+y //3
//只有一条语句时通常把{}省略,会自动返回执行结果
}
fun(1,2)
btn1.onclick = () =>{
alert(this) //点击btn1之后发现this指向window
}
let obh = {
name:'Tom'
getName(){
btn1.onclick = () =>{
alert(this)
}
}
}
obj.getName() //点击btn1之后发现this指向obj
点点点运算符
用途:
1.rest(可变)参数,用来取代arguments,但比arguments灵活,只能是最后部分形参参数,后面不能跟其他形参
2.扩展运算符
何为arguments
funciton foo(a,b){
console.log(arguments)
arguments.callee() //指向函数本身
arguments.forEach(function(item,index){
console.log(item,index) //报错
})
}
foo(1,2)
//arguments是个伪数组
funciton foo(...value){ //通过三点运算符收集的实参形成数组赋给value
console.log(arguments)
console.log(value) //真数组,取代了arguments
value.forEach(function(item,index){
console.log(item,index) // 1,0
})
}
foo(1)
funciton foo(a,...value){ //通过三点运算符收集的实参形成数组赋给value
console.log(arguments)
console.log(value) //真数组,取代了arguments,[2]
value.forEach(function(item,index){
console.log(item,index) // 2,0
})
}
foo(1,2) //第一个1给了形参a
let arr = [1,6]
let arr1 = [2,3,4,5]
//console.log(...arr1) 相当于把arr1数组遍历把每个值拿出来变成2,3,4,5
arr = [1, ...arr1,6] //[1,2,3,4,5,6]
形参默认值
function Fun(x=0,y=0){
this.x=x
this.y=y
}
let fun = new Fun(1,2)
fun.x //1
fun.y //2
let fun1 = new Fun()
fun.x //0
fun.y //0
Promise对象
理解:
1.Promise对象:代表了未来某个将要发生的事件(通常是一个异步操作)
2.有了Promise对象,可以将异步操作以同步的流程表达出来,避免了层层嵌套的回调函数(回调地狱:回调函数多的时候有很多嵌套,中间某个环节出了问题,不好解决,因为回调函数无法控制。还有一种回调函数之间的耦合度比较高,互相有依赖关系,导致不可预期的错误发生)
3.ES6的Promise是一个构造函数,用来生成promise实例
使用promise的基本步骤(2步)
//创建promise对象
let promise = new Promise((resolve,reject)=>{
//初始化promise状态为pending
//执行异步操作,通常是发送ajax请求,开启定时器
console.log(111)
setTimeout(()=>{
console.log(333)
//根据异步任务的返回结果来去修改promise状态
//异步任务执行成功
resolve('hh成功了') //自动修改promise的状态为fullfilled 成功状态
//异步任务执行失败
reject('失败了~') //修改promise的状态为rejected 失败状态
},2000)
})
console(222) // 111 222 333
//调用promise的then()
promise.then((data)=>{
//成功的回调,当状态还为初始化时,不会调用,状态变为成功时调用
console.log(data) //hh成功了
} , (error)=>{
//失败的回调,状态变为失败时调用
console.log(error) //失败了~
})
promise对象的3个状态 1.pending:初始化状态 2.fullfilled:成功状态 3.rejected:失败状态
应用: 使用promise实现超时处理
使用promise封装处理ajax请求
symbol
概念:ES6中添加了一种原始数据类型symbol
特点:
1.symbol属性对应的值是唯一的,解决命名冲突问题
2.symbol值不能与其他数据进行计算,包括同字符串拼串
3.for in,for of遍历时不会遍历symbol属性
使用:
//调用symbol函数得到symbol值
let symbol = Symbol() //不像构造函数要去new
console.log(symbol) //Symbol()
let obj ={name:'Tom',age:12}
//obj.sex = '男'
//obj.symbol = 'hello' 只是给obj添加了一个叫symbol的属性
obj[symbol] = 'hello' //obj多了symbol():'hello'
//for in , for of不能遍历symbol属性
for(let i in obj){
console.log(i) //没有symbol
}
//可以去定义常量
const Person_key = Symbol('person_key')
console.log(Person_key) //Symbol(person_key)
//传参标识
let symbol2 = Symbol('one')
let symbol3 = Symbol('two')
console.log(symbol2 == symbol3) //false
console.log(symbol2,symbol3) //Symbol(one) Symbol(two)
内置symbol值 ES6提供了11个内置的Symbol值,指向语言内部的使用方法 Symbol.iterator属性指向该对象的默认遍历器方法
iterator遍历器
概念:iterator是一种借口机制,为各种不同的数据结构提供统一的访问机制
作用
1.为各种数据结构提供一个统一的,简便的访问接口
2.使得数据结构的成员能够按某种次序排列
3.ES6创造了一种新的遍历命令for of循环,iterator接口主要供for of消费
工作原理:
1.创建一个指针对象(遍历器对象),指向数据结构的起始位置
2.第一次调用next方法,指针自动指向数据结构的第一个成员
3.接下来不断调用next方法,指针会一直往后移动,直到指向最后一个成员
4.每调用next方法返回的是一个包含value和done的对象,{value:当前成员的值 , done:布尔值} *value表示当前成员的值,done对应的布尔值表示当前的数据结构是否遍历结束 *当遍历结束的时候value返回undefined,done返回true
原生具备iterator接口的数据(可用for of遍历)
扩展理解: 1.当数据结构上部署了Symbol.iterator接口,该数据就是可以用for of遍历 2.当使用for of去遍历目标数据时,该数据会自动寻找Symbol.iterator属性
//模拟指针对象(遍历器对象)
function myIterator(arr){ //iterator接口
let nextIndex = 0 //记录指针位置
return {
//遍历器对象
next: function(){
return nextIndex < arr.length?{value:arr[nextIndex++],done:false}:{value:undefined,done:true}
}
}
}
let arr = [4,1,65,'abc']
let iteratorObj = myIterator(arr)
console.log(iteratorObj.next()) //4
console.log(iteratorObj.next()) //1
console.log(iteratorObj.next()) //65
console.log(iteratorObj.next()) //'abc'
console.log(iteratorObj.next()) //undefined true
//将iterator接口部署到指定的数据类型上,可以使用for of去循环遍历
//数组,字符串,arguments,set容器,map容器
//对象没有iterator接口
for(let i of arr){
console.log(i) //4,1,65,'abc'
}
let str = 'abcdefg'
for(let i of str){
console.log(i) //a,b,c,d,e,g
}
function fun(){
for(let i of arguments){
console.iog(i)
}
}
fun(1,4,5,'abc') //1,4,5,'abc'
let targetData = { //等同于在指定的数据内结构上部署了iterator接口
//当使用for of去遍历某一个数据结构时,首先去找Symbol.iterator,找到了就去遍历,没有就报错
[Symbol.iterator]:function(){
let nextIndex = 0 //记录指针位置
return {
//遍历器对象
next: function(){
return nextIndex < this.length?{value:this[nextIndex++],done:false}:{value:undefined,done:true}
}
}
}
}
//使用三点运算符,解构赋值,默认调用iterator接口
let arr2 = [1,6]
let arr3 = [2,3,4,5]
arr2 = [1,...arr3,6]
let [a,b] = arr2
console.log(a,b) //1,2
Genrator函数
概念:
1.ES6提供的解决异步编程方案之一
2.Genrator函数是一个状态机,内部封装了不同状态的数据
3.用来生成遍历器对象 4.可暂停函数(惰性求值),yield可暂停,next方法可启动。每次返回的是yield后的表达式结果
特点: 1.function与函数名之间有个*号
2.内部用yield表达式来定义不同的状态
3.generator函数返回的是指针对象,而不会执行函数的内部逻辑
4.调用next方法函数内部逻辑开始执行,遇到yield表达式停止,返回{value: field后的表达式结果,done:布尔值}
5.再次调用next方法会从上一次停止时的yield处开始,直到最后 6.yield语句返回结果通常为undefined,当调用next方法时,传参内容会作为启动时yield语句的返回值
function* generatorExample(){
console.log(1)
let result = yield 'hello' //状态值为hello
console.log(result) //aaaaaaa 不传的话为undefined
console.log(2)
yield 'generator' //状态值为generator
return '3'
}
let MG = generatorExample()
//MG.next() //1 没有2第一次在'hello'暂停了
console.log(MG.next()) //{value: 'hello',done:false}
console.log(MG.next('aaaaaaa')) //2 {value:'generator',done:false}
console.log(MG.next()) //{value:3,done:true}
//对象的symbol.iterator属性 指向遍历器对象
let obj ={name:'Tom',age:39}
for(let i of obj){
console.log(i) //报错
}
obj[symbol.iterator] = function* myTest(){
//返回一个遍历器对象,相当于给对象认为部署了一个iterator接口
yield 1
yield 2
yield 3
}
for(let i of obj){
console.log(i) //1 2 3
}
async函数
概念: 真正意义上去解决异步回调的问题,同步流程表达异步操作
本质:Generator的语法糖
语法: async function foo(){ await 异步操作; await 异步操作; }
特点: 1.不需要像Generator去调用next方法,遇到await等待,当前的异步操作完成就往下执行
2.返回的总是Promise对象,可以用then方法进行下一步操作
3.async取代Generator函数的星号*,await取代yield
4.语意上更为明确,使用简单,暂时没有任何副作用
function foo(){
return new Promise(resolve => {
setTimeout(resolve,2000)
})
}
async function test(){
console('开始执行',new Date().toTimeString())
await foo()
console('执行结束',new Date().toTimeString())
}
text() //开始执行 隔了两秒 执行结束
//async里的await返回值
function fun1(){
return 1
}
async function fun(){
let result = await fun1()
console.log(result)
}
fun() //1
async function fun(){
let result = await Promise.resolve('aaa') //直接把Promise对象改为成功状态
console.log(result) //aaa
result = await Promise.reject('bbb')
console.log(result) //报错
}
fun()
class类使用
1.通过class定义类,实现类的继承
2.在类中通过constructor定义构造方法
3.通过new来创建类的实例
4.通过extends来实现类的继承
5.通过super调用父类构造方法
6.重写从父类继承的一般方法
function Person(name,age){
this.name = name
this.age = age
}
let person = new Person('Tom',12)
//定义一个人物的类
class Person {
//类的构造方法
constructor(name , age){
this.name = name
this.age = age
}
//类的一般方法
showName(){
console.log(this.name)
} //放在实例对象的隐式原型上
}
let person = new Person('Tom',12)
person.showName() //Tom
class StarPerson extends Person{
constructor(name,age,salary){
super(name,age)//调用父类的构造方法
this.salary = salary
}
showName(){
//父类的方法重写
console.log(this.name,this.age,this.salary)
}
}
let p1 = new StarPerson('Jack',20,5000)
console.log(p1)
p1.showName()
字符串扩展
1.includes(str):判断是否包含指定的字符串
2.startsWith(str):判断是否以指定字符串开头
3.endsWith(str):判断是否以指定字符串结尾
4.repeat(count):重复指定次数
let str = 'a'
console.log(str.includes('a')) //true
console.log(str.startsWith('b')) //false
console.log(str.endsWith('a')) //true
console.log(str.repeat(5)) //aaaaa
数组方法的扩展
1.Array.from(v):可以将伪数组或可遍历对象转换成真实数组
2.Array.of(v1,v2,v3):将一系列值转换成数组
3.find(function(value,index,arr){return true}):找出第一个满足条件返回true的元素
4.findIndex(function(value,index,arr){return true}):找出第一个满足条件返回true的元素下标
let arr = [2,3,4,3,6]
let a = arr.find(function (item,index){
return item>=4
})
console.log(a) //4
对象方法扩展
1.Object.is(v1,v2) 判断两个数据是否完全相等
2.Object.assign(target,source1,source2) 将源对象的属性复制到目标对象上
3.直接操作__proto__属性
console.log(0 == -0) //true
console.log(Object.is(0,-0)) //flase
console.log(Object.is(NaN,NaN))//true 因为是用字符串的形式来判断
let obj = {}
let obj1 = {name:'Tom' , age:12}
let obj2 = {name:'Jack' , age:20}
let obj3 = {salary:5000}
Object.assign(obj,obj1,obj2,obj3)
console.log(obj) //{ name: 'Jack', age: 20, salary: 5000 }
let obj1={}
let obj2 ={money:50000}
obj1.__proto__ =obj2
console.log(obj1.money); //obj1.__proto__指向了obj2这个对象,obj1可以通过原型链寻找得到这个对象的属性
深度克隆
let str = 'abcd'
let str2 = str
str2 = ''
console.log(str) //abcd
//拷贝数组/对象 没有生成新的数据,而是复制了一份引用
let arr = {1,4,{name:'Tom',age:12}}
let arr2 = arr
arr2[0] = 'abcd'
console.log(arr[0]) //abcd
浅拷贝(对象/数组): 特点:拷贝的是引用,修改拷贝以后的数据会影响原数据,使得原数据不安全
深拷贝(深度克隆): 特点:拷贝的时候生成新数据,修改新数据不会影响原数据
拷贝数据: 基本数据类型:拷贝后生成一份新的数据,修改拷贝以后的数据不会影响原数据
对象数组:拷贝后不会生成新的数据,而是拷贝的是引用。修改拷贝之后的数据会影响原来的数据
拷贝数据的方法:
1.直接赋值给一个变量 浅拷贝
2.Object.assign() 浅拷贝
3.Array.prototype.concat() 浅拷贝
4.Array.prototype.slice(startIndex,endIndex) 截取子数组 浅拷贝
5.ISON.parse(JSON.stringify()) 深拷贝(深度克隆),拷贝的数据里不能有函数,处理不了,因为这两个方法只能传入原生的JS对象或数组,传入函数转过来发现函数变成null
let obj = {name:'Tom'}
let obj2 = Object.assign(obj)
console.log(obj2)
obj2.name = 'Jack'
console.log(obj.name) //Jack
let arr = [1,2,{name:'Tom'}]
let arr2 = arr.concat()
arr2[2].name = 'a'
console.log(arr[2].name) //a
let arr3 = arr.slice() //相当于传整个数组[1,2,{name:'a'}]
arr3[2].name = 'b'
console.log(arr[2].name) //b
let arr = [1,2,{name:'Tom'}]
let arr2 = JSON.stringify(arr) //arr2是个JSON数组,是个字符串
arr2 = JSON.parse(arr2)
arr2[2].name = 'Jack'
console.log(arr[2].name) //Tom
如何实现深度克隆? 拷贝数据里有对象或数组,还要继续遍历对象或者数组拿到里面的每一项的值,一直到拿到的都是基本数据类型,然后再去复制,这就是深度克隆
知识点储备: 如何判断数据类型:arr ---> Array null--->Null
1.typeof返回的数据类型:String Number Boolean Undefined Object Function
2.Object.prototype.toString.call(obj)
let result = 'abcd'
resunlt = null
result = [1,2,3]
console.log(Object.prototype.toString.call(result)) //[Object String] [Object Null] [Object Array]
console.log(Object.prototype.toString.call(result).slice(8,-1)) //String Null Array
for in 循环对象的到属性名 数组得到下标
function checkType(tarhet){
return Object.prototype.toString.call(target).slice(8,-1)
}
console.log(checkType(result)) //Array
//实现深度克隆 针对对象数组
function clone(target){
//判断拷贝的数据类型
//result是最终克隆的数据
let result,targetType = checkType(target)
if(targetType === 'Objcect'){
result = {}
}
else if(targetType ==='Array'){
result = []
}
else{
return target
}
//遍历目标数据
for(let i in target){
//获取遍历数据结构的每一项值
let value = target[i]
//判断目标结构里的每一值是否存在对象/数组
if(checkType(value) ==='Object' || checkType(value) === 'Array'){
//继续遍历取到的value值
result[i] = clone(value)
}else{ //获取到的value是基本数据类型或者函数
result[i] =value
}
}
return result
}
let arr = [1,2,{age:12}]
let arr2 = clone(arr)
arr2[2] = 'a'
console.log(arr , arr2); //[ 1, 2, { age: 12 } ] [ 1, 2, 'a' ]
Set和Map容器
1.Set容器:无序不可重复的多个value的集合体 Set() Set(array) add(value) delete(value) has(value) clear() size()
2.Map容器:无序的key不重复的多个key-value的集合体 Map() Map(array) set(key,value) //添加 get(value) delete(value) has(value) clear() size()
let set = new Set([1,2,3,4,2,1])
console.log(set) //[1,2,3,4]
set.add(7)
console.log(set.size)//5
set.clear()//清空set
let map = new Map([['key','value'],[36,'age']])
map.set(78,'hh')
console.log(map) //Map { 'key' => 'value', 36 => 'age', 78 => 'hh' }
map.delete(36)
console.log(map)//Map { 'key' => 'value' , 78 => 'hh' }
Array.prototype.includes(value) :判断数组中是否包含指定value
let arr = [1,2,3,4,'abc']
console.log(arr.includes('a')) //false