super
关键字使得子类调用了父类中的构造函数,父类可使用子类传进来的属性进行各类运算,super
关键字 还能够调用父类的方法class Father{ constructor(x,y){ this.x=x; this.y=y; } sum(){ console.log(this.x+this.y) } say(){ return "我是爸爸" } } class Son extends Father{ constructor(x,y){ //调用了父类中的构造函数 super(x,y) //子类独有的属性 this.x=x; this.y=y } say(){ console.log(super.say()) } //子类独有方法 subtract(){ console.log(this.x-this.y) } } let son=new Son(5,3); son.subtract(); son.sum();
tips: 继承中的属性或者方法查找原则:就近原则
super
,必须放到this前面(必须先调用父类的构造方法,再使用子类构造方法)es6
中类没有变量提高,必须先定义类,才能经过类实例化对象\this
使用this
指向的是 建立的实例对象var that //等于构造函数里this 即ldh这个对象 class Star{ constructor(name,age){ that=this this.name=name this.age=age this.btn=document.querySelector('button'); this.btn.onclick=this.sing } } sing(){ /* 这个sing方法里的this,指向的是btn 这个按钮,由于这个按钮调用了这个函数 */ console.log(this) console.log(this.name) //输出undenfind console.log(that.name) //输出ldh } dance(){ /* 这个dance里面的this 指向的是实例对象 ldh 由于是ldh调用了这个函数 */ console.log(this) } let ldh= new Star(ldh,18) ldh.dance()
es5
不使用prototype
原型对象function Star(name,age){ this.name=name; this.age=age; this.sing=funtion(){ console.log(我会唱歌) } } var ldh=new Star('刘德华',18); var zxy=new Star('张学友',19); /* new多个,基本属性不会,但sing方法会开辟多个不一样的内存空间,存在内存浪费的现象 */。
es5
使用构造函数prototype
原型对象function Star(name,age){ this.name=name; this.age=age; Star.prototype.sing=funtion(){ console.log(我会唱歌) } } Star.prototype ={ /*若是咱们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数*/ constructor:Star } var ldh=new Star('刘德华',18); var zxy=new Star('张学友',19); ldh.sing() /* new多个,基本属性不会,但sing方法会开辟多个不一样的内存空间,存在内存浪费的现象 */。
原型对象html
prototype
为原型对象构造函数
经过原型
分配的函数是全部对象所共享的。构造函数
都有一个prototype
属性,指向另外一个对象,注意这个prototype
就是一个对象,这个对象
的全部属性
和方法
,都会被构造函数
所拥有。prototype
对象上,这样全部对象的实例就能够共享这些方法__proto__和 prototype 的区别ios
__proto__
是new
出来的实例的的原型对象prototype
是构造函数的原型对象git
tips:
es5
的构造函数方法很好用,可是存在浪费内存的问题,能够经过构造函数的原型对象来存放方法,使得方法在不一样对象中共享,起到节约内存的做用。
js成员的查找机制es6
function Star(name,age){ this.name=name; this.age=age; } Star.prototype.sing=function(){ console.log("我会唱歌"); } Star.prototype.sex='女' //构造函数原型成员 ,优先级中等 Object.prototype.sex="男"//object对象的原型成员 ,优先级最低 var ldh =new Star('刘德华',18) ldh.sex="男" //实例对象的原型成员 优先级最高 console.log(ldh.sex) //打印这个实例向上找,能够找到Object
tips: 每一个对象里都有 __proto__这个属性
console.log(Array.prototype) 能够打印js的一些关于数组的api //在Array对象上添加自定义方法 Array.prototype.sum=function(){ var sum=0; for(var i=0;i<thsi.length;i++){ sum+=this[i]; } return sum; } var arr=[1,2,3]; console.log(arr.sum()) var arr =new Array(11,22,33) arr.sum(); //不可采用如下方法加入方法 Array.prototype= { sum: function(){ var sum=0; for(var i=0;i<thsi.length;i++){ sum+=this[i]; } return sum; } }
tips: 本身加的原型
方法会高亮,不可采用对象
的方式去添加原型方法,会覆盖原先就存在的方法。
call
方法call
能够调用函数。this
指向。this
的指向要被改变到这个参数的。function fn(x,y){ console.log('我想喝手磨咖啡'); console.log(this); console.log(x,y); } var o={ name:'andy' } fn.call() /* 此时这个函数的this,就指向了o这个对象,指向哪一个对象根据第一个参数决定*/ fn.call(o,1,2) 1. 父构造函数 function Father(name,age){ //this 指向父构造函数的对象实例 this.name=name; this.age=age; } 2. 子构造函数 //这个score用的son本身的属性 function Son(name,age,score){ //this 指向子构造函数的对象实例, //用call来调用Father这个构造函数,并把指向改为子类的构造函数的this,就实现了继承 Father.call(this,name,age) this.score=score } var son=new Son('刘德华',18,200) console.log(son)
prototype
继承方法原型对象(prototype)继承方法,经过原型链向上找规则,
Father实例(找不到向上找)->Father的原型对象的方法
就能够继承方法了,且子son方法定义本身的方法时不会影响到父github
//Father 是es5的构造函数 son.prototype=new Father() son.prototype.constructor=son
类的本质其实仍是一个函数 咱们也能够简单的认为类就是构造函数的另一种写法面试
es5 经过构造函数+原型实现面向对象 编程有如下特色ajax
es6正则表达式
forEach 迭代遍历数组,break和retrun不会终止编程
var arr= [1,2,3]; arr.forEach((value,index,array)=>{ console.log("每一个数组元素"+value) console.log("每一个数组元素的索引号"+index) console.log("数组自己"+array) })
filter 主要用于筛选数组json
var arr=[12.66,4,88] var newArr=arr.filter((value,index,array)=>{ return value>=2 //知足条件就把值放到新数组里 })
tips:返回的是一个新数组,不会影响原来的数组
some
主要用于检测数组中的元素是否知足指定条件,通俗点查找数组中是否有知足条件的元素
var arr=[12.66,4,88] var flag=arr.some((value,index,array)=>{ return value>=2 //知足条件就是true }) arr=[12.66,4,88] var flag=arr.some((value,index,array)=>{ if(value>30){ return true } })
tips:返回的是一个布尔值,若是查找到这个元素就返回true,再也不进行循环,效率更高。
trim 去除左右两边的空格,但不会去除中间的空格
str.trim()
定义对象中新属性或修改原有的属性
object.defineProperty(obj,prop,descriptor)
object.defineProperty
的参数
参数 | 是否必需 | 类型 | 说明 |
---|---|---|---|
obj | true | Object | 目标对象 |
prop | true | String | 需新定义或修改的属性的名字 |
descriptor | true | Object | 目标属性所拥有的的特性 |
var obj={ id:1, pname:"小米", price:1999 } //对对象定义新属性并赋值,之前的写法 obj.num=1000; obj.price=99; //如今的写法 Object.defineProperty(obj,'num',{ })
第三个参数descriptor的参数
参数 | 是否必需 | 类型 | 说明 |
---|---|---|---|
value | false | mixed | 设置属性的值 默认undefined |
writable | false | boolean | 是否能够重写 默认false |
ebumerable | false | boolean | 目标是否能够被枚举(遍历),默认false |
configurable | false | boolean | 目标属性是否能够被删除或是否能够再次修改特性true/false 默认为false |
tips: 注意新定义的descriptor 都是默认为false 用obj={} 来定义的由于没有定义是否能够被XX操做因此都是true
全部的函数都是Function的实例(对象),函数也是个对象,万物皆对象
1、 函数的定义方式
1.自定义函数(命名函数)
function fn(){};
2.函数表达式(匿名函数)
var fun =function(){ }
3.利用new Function (不推荐,效率低)
new Function('参数1','参数2','函数体')
参数 | 是否必需 | 类型 | 说明 |
---|---|---|---|
参数1 | false | String | 第一个参数 |
参数2 | false | String | 第二个参数 |
函数体 | false | String | 第三个参数 |
tips:若是只有一个参数那么就是函数体
二 、 函数的调用方式
1.普通函数
this
指向window
function fn(){ console.log('人生的巅峰') } fn() (window.fn()) fn.call()
2.对象的方法
this
指向o
var o ={ sayHi:function(){ console.log('人生的巅峰') } } o.sayHi();
3.构造函数
this
指向实例对象
function Star(){}; new Star();
4.绑定事件函数
this
指向是函数的调用者btn
这个按钮对象
//点击了按钮就能够调用这个函数 btn.onclick=function(){};
5.定时器函数
this
指向的是window
这个函数式定时器自动1秒钟调用一次
setInterval(function(){ },1000);
6.当即执行函数
this
指向window
(function(){ console.log('人生的巅峰') })()
tips: 当即执行函数是自动调用
调用方式 | this指向 |
---|---|
普通函数调用 | window |
构造函数调用 | 实例对象,原型对象里面的方法也指向实例对象 |
对象方法调用 | 该方法所属对象 |
事件绑定方法 | 事件绑定对 |
定时器函数 | window |
当即执行函数 | window |
call
var o={ name:"1" } functon fn(a,b){ console.log(a+b) } fn.call(o,1,2)
tips: 后两个参数是形参 用于参与fn的一些对象,主要用于在es5中实现继承
apply
var o={ name:"1" } functon fn(a,b){ console.log(a+b) } fn.apply(o,[1,2]) var arr=[1,66,4] //若是不想改变this(指定对象)就写个null,但不合适写Math就好了 Math.max.apply(Math,arr)
tips:参数必须是数组,但打印后倒是字符串或是数字(根据数组里的数据类型,断定)
bind
var o={ name:"1" } functon fn(a,b){ console.log(a+b) } var f= fn.bind(o); f(); //亦或者是 functon fn(a,b){ console.log(a+b) }.bind(this)
区别点:
主要应用场景:
做用:
js
语法的一些不合理、不严谨、减小了一些怪异行为。es
的将来版本中可能会定义的一些语法,为将来新版本的js
作好铺垫。好比一些保留字如:class
,enum
,export
,extends
,import
,super
不能作变量名变化
先声明
再使用随意删除
已经声明好
的变量this
是undefined
而不是window
new
也能够调用,当前普通函数,this
指向全局,在严格模式下不能使用了,this指向undefined
。//为整个脚本开启严格模式 <script> 'use strict'; </script> <script> (function()){ 'use strict'; }() </script> //为某个函数开启严格模式 <script> function fn(){ 'use strict'; /*里面的代码按照严格模式执行*/ } function fun(){ /*里面的仍是按照普通模式执行*/ } </script>
tips:兼容ie10以上,ie10如下会忽略这个模式
高阶函数- 函数能够做为参数传递,参数的接收方就是高阶函数,即 fn
function fn (a,b,callback){ console.log(a+b); callback && callback() } fn(1,2,function(){ console.log(我是最后调用的); })
function fn (){ var num=10; function fun(){ console.log(num) } fun () } fn
function fn(){ var num=10; return function(){ console.log(num) } } //这里f保存的是个函数 var f=fn() //这里输出的是num f()
for (var i=0;i<lis.length;i++){ /*利用for循环建立了4个当即函数*/ /*当即执行函数也成为小闭包由于当即执行函数里面的任何一个函数,均可以使用它的i这个变量*/ /*这里的i是从底下的那个i传进来的*/ (function(i){ lis[i].onclick=function() { console.log(i) } })(i)
tips:闭包的主要做用:延伸变量的做用范围。但闭包容易照成内存泄漏,它一直不释放资源,闭包总结:闭包是一个函数,闭包延伸了做用域范围
function fn(n){ if(n==1) return 1; return n*fn(n-1); } console.log(fn(3)) 执行过程 return 3*fn(2) return 3*(2*fn(1)) return 3*(2*1) return 6
function fb(n){ if(n===1 || n===2){ return 1 } return fn(n-1)+fb(n+2); } console.log(fb(3)) console.log(fb(3))
var data=[ { id :1, name:'家电' goods':[ { id :11, name:'家电11' }, { id :12, name:'家电12' } ] } { id :2, name:'家电2' goods':[ { id :13, name:'家电13' } ] } ] function getID(json,id){ var o ={}; json.forEach(function(item)) { if(item.id==id){ console.log(item); o=item; }else if(item.goods&&item.goods.learth>0){ o= getID(item.goods,id) } } } console.log(getID(data,1))
tips: 开辟内存空间,容易照成死递归,出现栈溢出。在forEach里面执行递归,不加退出条件,循环已经帮你加了。
var obj={ id:1, name:"andy", msg:{ //这个对象是深层次对象会被浅拷贝,会被拷贝地址,修改o同时会修改obj,这个就是浅拷贝 age:18 } } var o={} for(var k in obj){ //k 是属性名 // obj[k] 属性名 o[k]=obj[k]; } console.log(o); o.msg.age=20; console.log(obj)
2.es6的语法糖实现浅拷贝
Object.assign(o) /*主要用来对,对象赋值, key值相同的会覆盖 其余没进行赋值的不会处理,由于是浅拷贝因此会影响原数组 */
function deepCopy(newobj,oldobj){ for(var k in oldobj){ var item=oldobj[k]; if(item instanceof Array){ newobj[k]=[]; //判断是不是数组 deepCopy(newobj[k],item) }else if(item instanceof Object){ //判断是不是对象 newobj[k]={}; deepCopy(newobj[k],item) }else{ // 简单数据类型 newobj[k]=item; } } }
2.用JSON.stringify()和 jSON.parse() 来实现 深拷贝
tips: 数组也属于Object 因此要把Array判断写在object的前面。总结:浅拷贝,深层次的数据如数组和对象只会拷贝引用,修改拷贝后的数据会同时修改原来的被拷贝的的数据,深拷贝,是对数组和对象开辟不一样的空间,被拷贝的的数据。
灵活性、逻辑性和功能性很是的强,
能够迅速地用极简单的方式达到字符串的复杂控制
RegExp
对象来建立 正则表达式var regexp=new RegExp(/123/) console.log(regexp)
2.利用字面量
,建立正则表达式,即用//即注释的中间写上规则匹配就是正则表达式了
var rg=/123/; /* 可用test 方法来检测是否符合正则表 返回true或false */ var rg=/123/; console.log(rg.test(123));
var rg=/^abc/ ^匹配的是开头,这里的是abc var rg=/^abc$/ 精确匹配 只有输入abc 才会匹配
/* 只要包含a,或者b,或c,其中一个就能够了 */ var rg=/[abc]/ /* 只能选择一个a或者b或者c其中的一个 三选一 */ var rg=/^[abc]$/ /* 只能选择一个a-z,26字符中其中的一个字符,26选一 表示到a到z的范围 能够在[]中添加各类字符组合 */ var rg=/^[a-zA-z]$/ /* 若是中括号里 ^ 表示取反的意思 不要和边界符 ^ 混淆 取反即 如下就不能是 a-z和A-z */ var rg=/^[^a-zA-z]$/
//* 至关于>=0 能够出现0次或者不少次 var rg=/^a*$/; console.log(rg.test('')) console.log(rg.test('aaa')) //+ 至关于>=1 能够出现1次或者不少次,不能不出现,即0次 var rg=/^a+$/; console.log(rg.test('')) console.log(rg.test('aaa')) //? 至关于 1 || 0 能够出现1次或者0次 var rg=/^a?$/; console.log(rg.test('')) console.log(rg.test('a')) console.log(rg.test('aaa')) //{3}就是重复出现3次 var rg=/^a{3}$/; console.log(rg.test('')) console.log(rg.test('aa')) console.log(rg.test('aaa')) //{3,}出现大于等于3 console.log(rg.test('')) console.log(rg.test('aaa')) //{3,16}出现大于等于3而且小于等于16 var rg=/^a{3,16}$/; console.log(rg.test('')) console.log(rg.test('a'))
模式是 :[a-zA-z] 某个规则 量词符:{6,16} 这个规则的里字符可出现的次数 即只能出现6-16个a-zA-z 里的字符 且所有合起来只能有6-16个。 var rg=/^[a-zA-z]{6,16}$/
//这里有小括号因此表示 abc 重复3次 var rg=/^(abc){3}/ //这里没有小括号 c 重复3次 var rg=/^abc{3}/
预约类 | 说明 |
---|---|
d | 匹配0-9之间的任一数字,至关于[0-9] |
D | 匹配0-9之外的字符,至关于1 |
w | 匹配任意的字母、数字、和下划线,至关于[A-Za-z0-9_] |
W | 匹配任意的字母、数字和下划线之外的字符,至关于2 |
s | 匹配空格(包括换行符、制表符、空格符等),至关于[trnvf] |
S | 匹配非空格(至关于3 |
//座机号码验证 010-12345678 0591-1234567 //第一种 var reg=/^\d{3}-\d{8}|\d{4}-\d{7}$/ //第二种 var reg=/^\d{3,4}-\d{7,8}$/
//手机号码的正则表达式 var rg=/^1[3|4|5|7|8]\d{9}$/;
//qq号的正则 10000开始 var rg=/^[1-9]\d{4,}$/
var str=str.replace(/andy/,bady)
参数 | 说明 |
---|---|
第一个参数 | 被替换的字符串或者正则表达式 |
第二个参数 | 替换为的字符串 |
返回值 是一个替换完毕的新字符串
tips: 正则表达式里面不须要加引号, 无论是数字型仍是字符串型,正则表达式的中间不要有空格即//里添加的内容不要用空格来间隔
es六、es7
的知识点let
关键字if(true){ let a=1; var b=3 } console.log(a) //访问不到 undefined console.log(b) //访问的到,输出3
var num =10 if(true){ console.log(num) undefined let num=1 } /* num输出在块级做用域里,使用的是块级的做用域定义的变量,并且是在未定义前输出因此是undefined */
for (var i=0;i<10;i++){ console.log(i) setTimeOut(function(){ console.log(`i:${i}`) }) } 在var定义的变量下,定时器里输出的都是10 由于此时循环已经结束了,i是最后的一个值。 用let 能够正常循环输出
const
关键字常量赋值后,内存地址(值)不能修改,分两种状况
const a =1 a=3 //报错,值不能更改 const arr=[1,2] arr[0]=3 //可更改,只是更改结构内部的值 arr=[3,2] arr=[34,44] //不可更改总体都更改,是地址的更改,不容许
tips: 若是让对象里的属性不可进行修改可使用es5的方法 Object.freeze(arr) 此时 arr内部的属性也不能更改
let [a,b,c]=[1,2,3] || []; console.log(a,b,c,d,e) a 、b、c 输出 1,2,3 d,e是undefined
let person ={name:'zhangsan',age:20} let {name,age}=person || {} console.log(name) //zhangsan console.log(age) // 20 let {name:myName,ages:myAge}=person console.log(myName,myAge) //也能够输出
//第一种状况,把整个的对象赋值给另外一个读写 let user = { a: 1,b: 2,c: 3,d: 4,e: 5} let { aa = { a: user.a, b: user.b }, bb = { ...user } } = {} /* 第二种状况,能够把对象的值分配到不一样的对象 */ let users = {}, userDetails = {}; ({ a: users.a, b: users.b, ...userDetails } = user); console.log(users, userDetails) //users {a:1,b:2} userDetails {c:3,d:4,e:5}
const Tom={ name: 'Tom jones', age:25, family:{ mother: 'Norah Jones', father: 'Richard Jones', brother: 'Howard Jones' } } //只有在变量是underfine时,才能使用默认值 null false 0 都是有值的 const { father:f,mother:m,brother='sss' } = Tom.family || {} ; //以上的f、m 是别名 输出用别名
let a=10 let b=20 [a,b]=[b,a] console.log(a,b) //a输出 20 b输出10
tips: 第二种状况,必定要加上括号。
function sum(num1,num2){ return num1+num2 } const sum=(n1,n2)=>{ return n1+n2 } //以上代码只有一行,且return这行代码就能够简写为 const sum=(n1,n2) => n1+n2
var num=10 let obj={ num:1 say:(){ console.log(this.num) } } obj.say() //这里输出的是10
const gg=()=>{ console.log(1) }
不适用箭头函数的状况
1.做为构造函数,一个方法须要绑定到对象 const Person=function(name,points){ this.name=name this.points=points; } const jelly=new Person('jelly',5); 2.原型添加方法 Person.prototype.updatePoints=function(){ this.points++ console.log(this.points) } 3.事件 const button=document.querySelector('.zoom'); button.addEventListener('click',function(){ }) 4.须要使用arguments const sum =function(arguments){ /*arguments不是个真正的数组 须要用Array.from 转换 或用扩展运算符[...arguments]来转换*/ return Array.from(arguments).reduce((prevSum,value)=>pervSum+value,0 ) }
tips: 对象是不产生做用域,指向的s是全局window,因此箭头函数的this,指向的是window,因此这里输出的是10
//定义个方法 const sum =(...args)=>{ let total=0; args.forEach(item=>{ total+=itme }) return total } sum(10,20) //args里保存着10和20 sum(10,20,30)//args里保存10,20,30
let ary1=['张三','李四','王五'] let [s1,...s2]=ary1 s1 //存着张三 s2 //接收剩余参数成为个新数组,存着李四和王五
扩展运算符
能够将数组或者对象转为用逗号分隔的参数序列let ary=[1,2,3]; ...ary //1,2,3 转为去掉括号的用逗号分隔的参数序列 console.log(...ary) 1 2 3
扩展运算符
可用于合并数组,生成的是新数组let ary1=[1,2,3] let ary2=[4,5,6] ...ary1 //1,2,4 ...ary2 //4,5,6 //第一种 let ary3=[...ary1,...ary2] //第二种 -- push方法能够有多个参数 ary3=ary1.push(...ary2)
扩展运算符
可将伪数组转为真正的数组,就可使用数组的一些方法var Odivs=document.getElementsByTagName('div') console.log(Odivs) //伪数组 可迭代遍历但没有数组方法 var ary=[...Odivs] ary.push('a') console.log(ary);
扩展运算符
是深拷贝,修改使用新生成的数组,不影响原来数组的值扩展运算符
的应用实践1. //把二维数组扩展成对象数组 [...array[1],...Array[1]] 输出 [object,object] 2. //可用来代替apply方法 const fruit=['apple','bananas','pear'] const newFruit=['orange','mongo'] //用apply合并数组,apply后面跟着的参数是数组 fruit.push.apply(fruit,newFruit) //用扩展运算符来合并 fruit.push(...newFruit)
扩展运算符
适用于函数的传参例子1 var arrayLike={ "0":"1", "1":"2", "length":2 } Array.from(arrayLike,item=>item*2) 例子2 const todos=document.querySelectorAll('li'); const names=Array.from(todos,todo=>todo.textContent); console.log(names)
const str='abc' console.log(Array.from(str)) [a,b,c]
let ary=[{ id:1, name:'张三' },{ id:2, name:'李四' } ] let target= ary.find(item=> item.id==2 )
let ary=[10,20,50] const index= ary.findIndex((item,index)=>itme>15) console.log(index)
let ary=["a","b",c] ary.includes("a")
当前方法能够弥补 new Array 构造方法返回结果不一致问题。
/*当参数只有一位的时候,返回的是长度为1的数组 [undefined*1],而不是[1] 只有当参数是多个的状况下才会返回正确的数据*/ new Array(1) array.of(1) 输出的是[1]
当遍历时遇到false时,就不执行了,返回false
let name=`帐上` let sayHello =`hello${name}`
let result={ name:"Zhangsan", age:20 } let html=` <div> <span>${result.name}</span> <span>${result.age}</span> </div> `
const fn=(){ return '我是fn函数' } let html=`我是模板字符${fn()}` const template=` <div class="greet"> <p> Hello </p> </div> `.trim() //模板字符串自己就是字符串,因此可使用字符串方法
function renderTodos(todos){ return ( `<ul> ${todos.map(todo=>` <li> ${todo.name} ${todo.completed?'√':'X'} </li>`).join('')} </ul> ` ) } //map 返回的是数组 循环渲染有,因此用join 去除
const user='Mary'; const topic='learn to use markdown' //模板字符串加方法 function highLight(strings,...values){ //strings 输出的是:has commented on your topic //values 输出的是:user和topic } const sentence= hightlight `${user} has commented on your topic ${topic} `
--String的扩展方法
let str='hello world'; str.startsWith('Hello') //true str.endsWith('!') 、//true //可传递第二个参数, 从第几个参数开始 str.startsWith('Hello',6)
repeat
方法表示将原字符串重复n
次,返回一个新字符串'x'.repeat(3) // "xxx" 'hello'.repeat(2) //hellohello
const id ='510300198007300366x' const fan ='I love Laravist.' function padder(string,length=25){ return `${'',repeat(Math.max(length-string.length,0))}${string}` } console.log(padder(id)) console.log(padder(fan))
支持数组、字符串等 但目前版本不支取对象的循环
Array.protype.frist=function() { return this[0] } const fruits=['Apple','Bannana','Orange','Mango']; fruits.describe='My favorite fruits'; for(let index in fruits ){ console.log(fruits[index] ) 会输出多余的值 } for(let index of fruits ){ console.log(index ) 只输出数组内的值 能够 break } //迭代器 for(let [index,fruit] of fruits.entries() ){ console.log(index,fruit ) 只输出数组内的值 能够 break }
set
数据结构es6
提供了新的数据结构Set
。它相似于数组,可是成员的值都是惟一的,没有重复的值。const s=new Set() s.size //看s的长度
es6
能够进行数组去重const s3=new Set(["a","b","b"]) //用扩展运算符,变成用逗号分隔的 const arr=[...s3]
set
内置方法
tips:
set
的方法可使用链式调用
set
遍历const s5=new Set(['a','b','c']) s5.forEach(value=>{ console.log(value) })
//接口返回数据结构--是个数组 0: {menu_id: 92, menu_name: "微信公众号", menu_fid: 0, menu_val: "92_wechat_publicnumber"} 1: {menu_id: 1, menu_name: "学校管理", menu_fid: 0, menu_val: "1_school"} 2: {menu_id: 2, menu_name: "教师管理", menu_fid: 0, menu_val: "2_psychologist"} 3: {menu_id: 3, menu_name: "学生管理", menu_fid: 0, menu_val: "3_counseling"} 4: {menu_id: 4, menu_name: "量表中心", menu_fid: 0, menu_val: "4_scale"} 5: {menu_id: 5, menu_name: "心理咨询", menu_fid: 0, menu_val: "5_advisory"} 6: {menu_id: 6, menu_name: "异常反馈", menu_fid: 0, menu_val: "6_abnormal"} 7: {menu_id: 7, menu_name: "活动管理", menu_fid: 0, menu_val: "7_activity"} 8: {menu_id: 8, menu_name: "在线求助", menu_fid: 0, menu_val: "8_help"} 9: {menu_id: 9, menu_name: "心理课堂", menu_fid: 0, menu_val: "9_classroom"} 10: {menu_id: 10, menu_name: "心理实验", menu_fid: 0, menu_val: "10_experiment"} 11: {menu_id: 11, menu_name: "订单管理", menu_fid: 0, menu_val: "11_order"} 12: {menu_id: 12, menu_name: "数据分析", menu_fid: 0, menu_val: "12_data"} 13: {menu_id: 14, menu_name: "学校列表", menu_fid: 1, menu_val: "14_school_list"} 14: {menu_id: 15, menu_name: "学校资讯", menu_fid: 1, menu_val: "15_information_list"} 15: {menu_id: 17, menu_name: "学校横幅", menu_fid: 1, menu_val: "17_schoolad_list"} 16: {menu_id: 18, menu_name: "老师列表", menu_fid: 2, menu_val: "18_psychologist_list"} 17: {menu_id: 19, menu_name: "老师导入", menu_fid: 2, menu_val: "19_teacher_import"} 18: {menu_id: 20, menu_name: "发送信息", menu_fid: 2, menu_val: "20_edit_notice"} 19: {menu_id: 21, menu_name: "学生列表", menu_fid: 3, menu_val: "21_counseling_list"} 20: {menu_id: 22, menu_name: "学生导入", menu_fid: 3, menu_val: "22_counseling_import"} 21: {menu_id: 23, menu_name: "发送信息", menu_fid: 3, menu_val: "23_edit_cou_notice"} 22: {menu_id: 24, menu_name: "用户统计", menu_fid: 3, menu_val: "24_user_count"} 23: {menu_id: 25, menu_name: "综合档案", menu_fid: 3, menu_val: "25_comprehensive_file"} 24: {menu_id: 26, menu_name: "量表分类", menu_fid: 4, menu_val: "26_scale_shape"} 25: {menu_id: 28, menu_name: "量表权限", menu_fid: 4, menu_val: "28_scale_rights"} 26: {menu_id: 29, menu_name: "测评查询", menu_fid: 4, menu_val: "29_assess_search"} //根据fid生成带孩子的二级树形结构--只有二级就简单点 getJsonTree (data, fId) { let itemArr = []; data.forEach(item => { const { menu_id = 0, menu_fid = 0, menu_name = '', menu_val = '' } = item || {} if (menu_fid === fId) { let newNode = { id: menu_id, label: menu_name, value: menu_val, checkAll: false, checkedOptions: [], options: this.getJsonTree(data, menu_id) //第一个是0写死的id找不到父亲的,找到的都是当父亲的,第二个就是把本身的id当作是fid 去找它的孩子 }; itemArr.push(newNode); } }) return itemArr; }, // 孩子的数组,特殊状况就用这个来代替 this.getJsonTree函数 (只限于二级) getChild (data, fId) { let itemArr = []; data.forEach(item => { const { menu_id = 0, menu_fid = 0, menu_name = '', menu_val = '' } = item || {} if (menu_fid === fId) { let newNode = { label: menu_name, value: menu_val, }; itemArr.push(newNode); } }) return itemArr; },
es6 对象 变的更增强大
const name='Lara' const age=2 const keys=['name','age'] const values=['lara',2] const laravist={ [keys.shift()]:values.shift(), [keys.shift()]:values.shift(), [keys.shift()]:values.shift(), }
const p=new Promise(reslove,reject)=>{ setTimeout()=>{ reject(Error('Error')) } }) p.then(data=>{console.log(data)}) .catch(err=>{console.log(err)})
tips: 在reject中使用Error返回错误信息时,使浏览器正肯定位到是reject那行发出的错误信息,而不是catch那行。
const userPromise=new Promise((resolove,reject)=>{ setTimeout(()=>{ reslove(['mojom','vanpe']) },2000) }) const moviePromise=new Promise(()=>{ setTimeout(()=>{ reslove({name:"摔跤",rat:9.2}) },500) }) Promise. all([userPromise,moviePromise]) .then(responses=>{ console.log(responses) }) .catch(responses=>{ console.log(responses) })
tips:Promise all
当以上全部promise
都正确执行时,才返回正确的,不然会被catch
捕获。
Promise race
同时调用多个promise
当第一个调用的promise 正确执行时就在then中返回结果,否则就在catch中返回
Symbol
是js的第七种数据类型, 其余6种:Undefined、Null、Boolean、Number和String,复杂的数据类型Objectconst peter=Symbol('peter'); const student=Symbol('student'); //如下nina两个key值重复,因此用Symbol来标识 const classRoom={ [Symbol('lily')]:{grade:60,gender:'female'}, [Symbol('nina')]:{grade:60,gender:'female'}, [Symbol('nina')]:{grade:60,gender:'female'}, } //for 循环不能遍历 for(let key of classRoom){ console.log(key) //输出[] } //另类遍历的方法 const syms=Object.getOwnPropertySymbols(classRoom).map(sym>classRoom[sym]) console.log(syms)
tips:classRoom[sym] 不能改为 classRoom.sym 这里会执行 classRoom['sym']但classRoom数据里并无sym这个属性名
eslint
代码规范eslint
会找当前目录的.eslintrc.js文件,若是找不到就往上级找/* globals Vue */ .eslintrc.js 文件中 globals: { Yx: true }
/* eslint-disable no-new */
/* eslint-enable no-new */
{ "plugins":["markdown"] }
静态方法 Reflect.ownKeys() 返回一个由目标对象自身的属性键组成的数组。
const object1 = { property1: 42, property2: 13 }; var array1 = []; console.log(Reflect.ownKeys(object1)); // expected output: Array ["property1", "property2"] console.log(Reflect.ownKeys(array1)); // expected output: Array ["length"]
转化为整形
//可使用+也可隐士转化为数字 +'243'
let methodName = 'info' class User { constructor(name,age){ this.name=name; this.age=age; } [methodName](){ console.log(1) } }
class student extends User { constructor(name,age){ super(name); /*super的做用及原理 做用 :继承父类,等同于User.call(this,name)调用基类的构造函数 原理: student.prototype=new User() 类的原型被改变了,可是类的原型的构造函数的也改变了,要指定构造函数为student student.prototype.constructor =student */ this.age=age; } }
为Array 添加本身的方法
class Movie extends Array { constructor(name,...items){ super(...item) this.name=name } add(movie){ // this.push(movie) } } const movies=new Movie('favorite movies', {name:'rr1',score:8.7}, {name:'rr2',score:99.7}, {name:'rr3',score:91.7} ) movies.add() //添加内容
遍历器(迭代器)
const colors=[1,2,3] const iterator= colors[Symbol.iterator]() iterator.next() /*输出*/ Object{value:1,done:false } iterator.next() /*输出*/ Object{value:2,done:false } iterator.next() /*输出*/ Object{value:3,done:false } iterator.next() /*输出*/ Object{value:undefined,done:true}
tips:
当done为true时遍历就结束了,输出一个方法时有包含Iterator,就是遍历器了,好比数组的 keys,entries,
values
//实现一个Array.values Array.prototype.values=function(){ let i = 0; let items = this; return{ //返回一个函数,造成闭包,能够进行累加 next(){ const done =i > = items.length; const value = done?undefined:items[i++] return{ value, done } } } }
for of 的运行机制
for(const itme of color){} //of调用,colors[Symbol.iterator]() 这个属性。 并把里面的value值赋值给color
function* listColors(){ let i=0; yield i; //返回 i++; yield i; i++; yield i; } //生成了遍历器 const colors=listColors(); colors.next() /*输出*/ Object{value:0,done:false} colors.next() /*输出*/ Object{value:1,done:false} colors.next() /*输出*/ Object{value:2,done:false} colors.next() /*输出*/ Object{value:undefined,done:true} const colors=[1,2,3] function* loop(repos){ console.log(colors) for(const repo of repos){ yield repo } } const repoGen=loop(repos)
//进行ajax方法 function ajax(url){ axios.get(url).then( res => 执行成功后再执行下一步 userGen.next(res.data) ) } //生成器 function* steps(){ const users = yield ajax('https://api.github.com/users'); const firstUser = yield ajax(`https://api.github.com/users/${users[0].login}`) const followers = yield ajax(firstUser.followers_url); } const userGen =steps() userGen.next()
const person = {name:'laravist',age:2000}; const personHandle={ //获取值 get(target,key){ //target:原目标; key:键值 //把属性值都转换成大写 return target[key].toUpperCase(); } //设置值 set(target,key,value){ //去掉空格 if(typeof value==='string'){ target[key]=value.trim() } } } const personProxy = new Proxy(person,personHandle) personProxy.name=' codecasts ' console.log(personProxy.name) // 输出:CODECASTS --去去掉空格并转换成大写
// 安全挟持 const safeHandler = { set(target,key,value){ //找相相似的键 const likekey = Object.keys(target).find(k=>k.toLowerCase()===key.toLowerCase()); //若是找到就不让其赋值 if(!(key in target) && likekey ){ throw new Error(` Oops! looks like we already have a property ${key} but with the case of ${likeKey}`) } } } const safetyProxy=new Proxy({id:2}, safeHandler); safetyProxy.ID=5 /*会报错,赋值已经被挟持了只要和id这个键值相相似的 好比 Id ID iD 都不让赋值*/
// 定义一个set const colors=new Set() colors.add(4)//添加元素 colors.delete(4)//删除 colors.has(4)//检验是否存在 /*能够用正常的数组循环方式进行循环*/ for(let color of colors ){ console.log(color) } colors.forEach(item=>{ console.log(item) })
const colorsSet=new Set([1,2,3,4,4,4,4]) const colorsArr=[...colorsSet] // 或者能够经过array.from() 来进行转换
const { jelly:{name:'jelly',age:20}, mary:{name:'mary',age:25} } ={} const weakPeople=new WeakSet([jelly,mary]) console.log(weakPeople) mary=null console.log(weakPeople) // mary 这个属性值就不见了, 若是用数组来存储,这个值仍是存在的
const people = new map(); people.set('jelly',23) people.has('jelly') //检验是否含有jelly这个值 people.delect('jelly') //进行删除 people.clear()所有删除 //对 fruits 进行赋值 const fruits = new Map([['apple',6],['banana',5]]) //用forEach和解构的方式来遍历map fruits.forEach([key,value]=>{ console.log(key,value) }) //若是不用解构方式,他返回的值是一整个是数组
const jelly = {name:'jelly'}; const miffy = {name:'miffy'} const strong= new Map(); const weak=new WeakMap(); strong.set(jelly,'jelly is the best!') weak.set(miffy,'miffy is the 2nd best!')