ES6-ES10语法
ES5严格模式
用来消除语法中不合理,不严谨之处,让代码运行更安全,提高编译效率
限定内容
1.必须用var声明变量
2.函数的顶层不再指向window,而是undefined
2.不能定义和eval同名的变量,也不能创建相同的函数
4.禁止使用delete删除
5.禁止使用arguments,calee,caller
6.禁止使用with语句
// "use strict"
with(location) {
console.log(hash)
console.log(href)
console.log(pathname)
}
7.禁止函数参数重名
8禁止对象属性重名
9.禁止使用八进制的关键字
10.不允许在非函数的代码块内
列如:
“use strict"
b=23
console.log(b)
Object方法
1.Object.freeze()冻结一个对象(只能查询)
2.Object.isFrozen()是否冻结对象
3.object.seal()密封一个对象(不能添加和删除)
4.object.isSeal()是否被密封
5.Object.preventExtensions()让一个对象不可被扩展(不能添加)
ES6语法
let const
let类似于var,用来定义变量,但是let没有变量提升,只在代码块内有效
1.没有变量提升
2.代码块内,可以创建私有变量
if(true){
let a=12
}
console.log(a)//报错
3.解决事件循环机制问题
for(let i=1; i<5;i++){
setTimeout(function(){
console.log(i)
})
}
4.暂时性死区
只要在块级作用中声明let,他就会绑定在这个区域,不再受外界影响
let a=1
function fun(){
//暂时性死区
a=2
let a
console.log(a)//报错,只找函数下的a 不去找全局的
}
5不允许重复声明
if(true){
var a=12
let a=55
console.log(a)//报错,不能重复声明
}
const命令
const声明常量,一旦声明,常量的值不能改变
1.const具有let的所有特点,没有变量提升,代码块内可以定义为私有变量,不能重复声明,存在暂时性死区
var a=12
const a=55
console.log(a)//报错,不能重复声明
2.一旦声明,值不能改变
const pi = 3.14
console.log(pi)
// pi = 3.5
var num = pi * 3
console.log(pi)报错
3.本质:如果是基本类型的值,保证的是值不能改变,如果哟是引用类型的值,保证对象的地址不能改变,
const arr=[1,2,3]
arr[0]=66
console.log(arr)//[66,2,3]
const arr={a:"zxc"}
console.log(arr)//报错
面试题:var let和const区别
1.var有变量提升,let和const没有变量提升
2.var在函数下是私有变量,let const在代码块呢是私有变量
3var可以重复定义,let constby不可以重复定义
4.var 没有暂时性死区,let const具有let的所有特点,没有变量提升,代码块内可以定义为私有变量,不能重复声明,存在暂时性死区
5.const定义的基本类型值保证值不能改变,引用类型值保证地址不能改变
声明方法
var let const function class import
解构赋值 let [a, b, c] = [1, 2, 3]
console.log(a)
console.log(b)
console.log(c)
用来快速取出变量,减少语法写作
例如:
数组结构赋值
1.解构赋值可以为任何类型,只要结构相对应
let[a,b,c]=[1,{name:"aa"},[22,33]]
2.可以缺少变量和值,但是不能类型不对应
let[a,b,c]=[1,2]//c是undefined
let[a,b,]=[1,2,3]//3没有赋给变量
let[a,b,c]=[1,,3]//b是undefined
let[a,b,c]={}//报错,数组结构对象
let[a,b,c]=22//报错,数组解构基本类型值
3.可以与拓展运算符连用
let [a, b, c, ...d] = [1, 2, 3, 45, 6, 89]、、扩展运算符只能放置在最后一个变量
4可以设置模式
let [a, b, c = 22] = [1, 2, undefined]//替代undefined
5.对象结构赋值
var obj={name:"list",age:23}
let {age,name}=obj
console.log(age)
console.log(name)
给属性重新命名,但是输出原属性名称,则报错
var obj={name:"list",age:23}
let {age:a,name:b}=obj
console.log(a)
console.log(b)
console.log(age)
console.log(name)
其他类型:
ES6引用对象
字符串的扩展
1.includes(字符串,位置)是否找到了匹配值,返回布尔
2.startWidth()判断是否以某个字符串开头,返回布尔
3.endWidth()判断是否以某个字符串结尾,返回布尔
4.repeat()把一个字符串重复n次
5.padstart(长度,字符串)头补全字符串
6.padEnd(长度,字符串)尾补全字符串
consoloe.log("138".padstart(11,"*"))
摸版字符串
摸版字符串是为了让我们拼接字符串,或者读取变量更简单
语法
1.模板字符串要定义在反单引号里
2.调用变量写在${}表达式里
3.摸版字符串下支持转义字符,例如:/n
执行
var name ="李四"
`<h1>姓名:${name}</h1>`
做运算
`<h1>姓名:${3+4}</h1>`
做三元表达式
`<h1>${age==23? "yes":'no'}<h1>`
调用函数
`<h1>${name.replace('i','#')}<h1>`
执行js的语法
alert`123`
function fun(){
return "zxc"
}
console.log(`${fun()}`)
数字的扩展
number
1.二进制 用0b或0B开头
2.八进制 用0o或0O开头
3,isNaN()判断是否为数字
4.parseInt()转换成整数
5.parseFloat()转换成浮点数
6.isFinite()是否为一个有限值
7.isInteger()判断是否是整数
数学的扩展
属性和方法
1.trunc()去除一个数的小数部分
2.sign()判断一个数是正数,负数,零,正数返回1,负数返回-1,零返回0
3.cbrt()求立方根
4.imul()返回带符号整数的乘积,非数字返回0
5.hypot()返回所有参数的平方和的平方根
6.指数运算符 2**3 //2*2*2=8
bigInt
js的数字类型存储长度有限,bigint存储长度无限制,所以计算时不用考虑数字的溢出问题,可以计算大数字加法,列如银行的钱数,但是只能存储整形数字
最大整数
定义
var num =23n
类型typeof 66n bigInt
判断10==10n// true
转化BigInt("23")//23
bigInt(true)//1
1n+2n=3,
2+3n//类型不同不能直接计算
数据类型:number,string,boolean,null,undefined,bigInt,symbol,Object
数组下的扩展
扩展运算符
表示方式:...,用把数组遍历成一个序列
列如:var arr=[1,2,3,4,3,5]
[...arr]
属性和方法
1.from()将对象转换成数组
2.of()将多个参数转换成数组
3.find(函数)返回查找的值,没有返回undefined
4.findIndex(函数)返回查找的位置,没有返回-1
5.fill(值)把值填充整个数组
6.keys()遍历所有key值
7.values()遍历所有value值
8.enties()遍历所有键值对
9.includes()判断是否包含指定值,返回布尔类型
10.copyWithin(替换位置,提取开始位置,结束位置)将数组中的指定值进行交换,
数组的空位
当定义一个数组,数组下没有给赋值,则数组下表存储的是空位,空位不是unddfined和null
,他不能参与其他值转化参与运算,如果非要输出,会默认输出undefined,但是不同方式处理空位不一样,
1.for/in foreach every some都会跳出空位
2.map会让空位保留,但不参与运算
3.for of,string,join把空位视为undefined
正则
正则是用字母,数字,符号组成,用来验证或筛选字符串内容,列入可以做表单验证,
定义:
let re=new REGexp("正则表达式","修饰符")
let re=new REGexp(/a/g)es6语法
let re=/a/g //简写
修饰符
i不区分大小写
g 全局匹配
m 实现多行匹配
u 以Unicode编码执行正则表达式(es6)
y 用来匹配多个值 ,只匹配粘连模式
s 匹配任意单个字符串,包括括号和转义字符
属性和方法
test()
验证字符串是否满足正则匹配,返回布尔值
exec()验证字符串是否满足正则匹配,返回字符串,否则null
compole()重新编译正则表达式
global是否设置了g,返回布尔值
ignoreCase 是否设置了i,返回布尔值
multiline 是否设置了m,返回布尔值
sticky是否设置了y修饰符,返回布尔值(es6语法)
flags返回正则表达式的修饰内容(es6)
source(返回正则表达式)
贪婪匹配:正则表达式返回的最长匹配懒惰匹配:正则表达式返回的最短匹配
varstr="asd/path-123/path-456/path-789" var re1=/(.*)(V)path-\d+/ var re2=/(.*?)(V)path-\d+/
console.log(str.match(re1))//贪婪匹配 console.log(str.match(re2))//懒惰匹配
前行断言后行断言
(?:a)可以匹配a前后的值(?=a)可以匹配a前面的值(?!a)反向匹配a前面的值
ES6新增 后行断言
(?<=a)可以匹配a后面的值(?<!a)反向匹配a后面的值
函数
函数
es6函数可以定义默认值
function fun(x=0,y=0){
return x+y
}
函数与扩展运算符连用
function fun(x,...arr){
console.log(x)
console.log(arr)
}
//函数与解构赋值连用
function fun([x,y,z]){
console.log(x,y,z)
}
fun([3,4,5])
function fun1({name:a,age:b}{
console.log(a)
console.log(b)
}
默认值的作用域:一日设苦了默认值,函数进行声明时,参数会形成一个单独的作用域等到初
始化结束时,这个作用域会消失,这种语法在默认值时,不会出现
var x=1
function fun(x,y=x){console.log(y) }
fun(2)
function fun1(y=x){
let x=2
console.log(y)
}
fun1()
函数下定义严格模式,不能使用es6语法
function fun(x=3){
"use strict'
console.log(x)
}
属性和方法
name获得函数的名称
length获得没有默认值的参数个数
例如
var foo=function goo(){
console.log(foo.name) //goo 因为函数goo付给第三方变量foo
}
例如:
function fun(x,y,z=1){}
console.log(fun.length)//2有两个参数不带默认值
function fun1(x,y=1,z){}
console.log(fun1.length)//1 当遇见一个默认值,则后面的变量都忽略不计
箭头函数
箭头函数用来简化函数体,用来解决this关键字的指向
//带参数和返回值的箭头函数
var fun=(a,b)=>a+b
//带一个函数的简写方法
var fun=a=>a
//无参数的函数
var fun=()=>5
//多行函数体
var fun=()=>{console.log(111)}
//带默认值的箭头函数
var fun=(a=0,b=1)=>a+b
//带扩展运算符
var fun=(a...b)=>a+b.join("")
//带解构赋值
var fun=([a,b])=>a+b
注意事项
1.箭头函数体内的this指向定义时所在对象,不是使用是所在的对象
2.箭头函数不能当做构造器使用,不能new命令,否则会报错
3.箭头函数里不可以使用argument,但是可以使用扩展运算符
4.不可以使用yield命令,不能用作Grenerator函数
例如:
var name="window"
var obj={
name:"obj",
say:function(){console.log(this.name)
fun:()=>{console.log(this.name)
}
obj.say()//obj
var foo=obj.say
foo() //window
obj.fun()//window
var f=obj.fun f
()//window
改变this指向
function Father(name,sex){
this.name=name
this.sex=sex
}
function Son(name,sex,age)
// Father.call(this,name,sex)
// Father.apply(this[name,sex]
// Father bind(this,name,sex)()
Son::Father(…[name,sex])//类似于apply
this.age=age
this.say=function(){
console.log(this.name,this.sex,this.age)
}
var s=new Son("小明","男",23)
s.say()
函数式编程
纯函数
一个函数的反回结果只依赖于的他的参数,叫做纯函数
普通函数:有副作用,函数会改变其他环境的变量
var a=1
function fun(b){ return a+b }
纯函数:只能函数内部,不受外界影响
function fun1(x,y) {return x+y}
高阶函数
在函数下接收一个函数作为参数,叫做高阶函数
你学过的高阶函数有什么?
settimeout,map,filter,forEacth
你自己写过的高阶函数
防抖函数和节流函数
function debouce(fun,time)//高阶
var ter=null
if(ter){clearTimeout(ter) }
else{
ter=setTimeout(function(){//闭包
fun()
},time)
}
柯里化函数
一个函数传入一部分参数,此时就会返回一个函数函数来接收剩余的参数
function add(a,b,c){
return function(b){
return function(c){
return a+b+c
}
}
}
console.log(add(1)(2)(3))
对象
创建对象属性的简写方式
var name="lisi"
var obj={name}
定义对象下的方法
var obj={
say(){
}
}
属性名表达式
var obj={name:"lisi"}
obj.name
obj["name"]
obj["na"+"me"]
属性和方法
1.Object.is()用来比较两个对象是否相等
2.Object.assign()用来赋值可枚举的属性
3.Object.setPrototype(孩子,父类)设置一个对象的父类
4.keys()遍历对象下的属性名
5.values()遍历对象下的属性值
6.entries()遍历对象下的键值对
7.Object.getOwnPropertyDescriptors()返回某个对象的属性的描述
对象遍历的区别
//遍历自身和继承的可枚举属性(不包含symbol属性)
// for (var v in s) {
// console.log(v)
// }
//遍历自身可枚举属性(不包含symbol属性)
// for (var v of Object.keys(s)) {
// console.log(v)
// }
//遍历自身属性,包含不可枚举(不包含symbol属性)
console.log(Object.getOwnPropertyNames(s))
//遍历自身所有symbol属性
console.log(Object.getOwnPropertySymobols(s))
//便利自身所有属性(包含不可枚举的和symbol属性)
console.log(Reflect.ownkeys(s))
symbol类型
js的对象属性名都是字符串类型,这样造成属性名冲突,symbol用来保证属性名是独一无二的,解决冲突问题
定义
var s1 = Symbol("name")
var s2 = Symbol("name")
类型:
// console.log(typeof s1)//symbol
判断
var s1 = Symbol("name")
var s2 = Symbol("name")
// console.log(s1 == s2)false
转化为字符传
var s1=symbol("name")
s1.tostring()//
定义对象下的属性
var s1 = Symbol("name")
var obj = {
name: "lisi",
name: "xiaoming",
}
方法1
obj[s1] = "xiaohong",
方法2
var p={[s1]:"小红"}
console.log(obj[s1., ])//xiaohong
方法3:
Object.definedProperty(obj,s1,{value:"aa"})
定义对象下的函数
var s1=Symbol("say")
var obj={[s1]:function(){//函数里的内容}}
obj[s1]()调用
属性和方法
Object.getOwnPropertySymobols()遍历对象下的symbol属性
Reflect.ownkeys()遍历对象下所有属性
Symbol.for()查找是否有匹配值,有值返回,没有创建
Symbol.keyfor()查找是否有匹配值,有值返回,没有返回undefined
Symbol.haslntance()判断该对象是否为某个构造器的实例,
Symbol.isConcatSpreadable()判断是否可以用数组拼接方法,返回布尔值
Symbol.species()指向当前对象的构造函数,
Symbol.match()用来返回查找的值
Symbol.replace()替换值
symbol.search()查找值的所在位置
symbol.split()分隔值
symbol的方法调用方式
var s1 = Symbol("name")
function foo() {
[s1] = "asd"
}
var f = new foo()
console.log(foo[Symbol.hasInstance](f))、、true
//数组拼接
/ var arr = ["a"]
// var arr1 = ["b"]
// console.log(arr[Symbol.isConcatSpreadable])//undefined
// arr[Symbol.isConcatSpreadable] = false
// console.log(arr.concat(arr1))//(2) [Array(1), 'b']
// arr[Symbol.isConcatSpreadable] = true
// console.log(arr.concat(arr1))//(2) ["a", 'b']
面向对象的class定义
在js里定义对象和后台语言不太相同,这样给程序学习时造成很大的困惑,所以es6提出用class声明对象,让语法更接近于后台语言,但是class只是一个语法糖,实际面向对象的思想还是和以前一样,
class Emp {
constructor(name, age) {
this.name = name
this.age = age
}
}
var e = new Emp("si", 19)
注意:
1.class关键字只是一个语法,底层结构和es5一样
2.class的实例上调用都是原型上的方法
e.constructor==Emp.setPrototype.constructor//true
3.在class声明体内都是严格模式
在函数下定义num=12报错。没有声明,
4.class声明的对象必须用new调用,否则会报错
Emp()没有用new声明,会报错
5.class声明的对象没有变量提升
6.class声明的对象可以用函数表达式的形式
var person = class pen {
constructor(name) {
this.name = name
}
}
var b = new person("lisi")
console.log(b)
私有变量和私有函数
在es6下没有提供私有的关键字,但是我们可以通过改变变量和函数名来模拟实现
class obj {
_x//私有变量
constructor(x) {
_x = x
}
}
var a = new obj(33)
console.log(a.x)、、报错,找不到变量
私有函数
class obj{
foo(){
_goo.call(this)
}
}
function _goo(){
console.log(222222)
}
p._goo()//报错
es6下的私有函数
var s=Symbol("goo")
class point{
[s](){
console.log(22222)
}
}
var p=new point()
p.goo()报错
class Emp{
constructor(){
this.printname=(name="aa")=>this.info(`hello ${name}`)
}
constructor(){
this.printname=this.printname.bind(this)
}
// printname(name="aa"){
// this.info(`hello ${name}`)
// }
info(n){
console.log(n)
}
}
var e=new Emp()
var {printname}= e
console.log(printname())
class下的geter和seter
class obj {
constructor(name) {
this.name = name
}
get names() {
return "触发get函数"
}
set names(name) {
console.log("触发set方法")
this.name = name
}
}
var a = new obj("lisi")
console.log(a.name)
a.names = "张三"
console.log(a.name)
static静态关键字
static修饰是静态方法和静态变量,当修饰方法时,方法不会被实例继承,方法和属性可以直接通过类名调用
class emp {
say() {
console.log(1111)
}
static info() {
console.log(2222)
}
}
console.log(emp.info())
var a = new emp()
console.log(a.info())//报错,实例继承不到
静态的思想,类似于es5下这样定义:
emp.info=function(){}//所有实例回访不到
静态变量
class emp {
static name = "lisi"
constructor() {
console.log(emp.name)//lisi
console.log(this.name)//undefined
}
}
console.log(emp.name)//lisi
var a = new emp()
console, log(a.name)//报错
new.target属性:判断对象是否通过new执行构造器,如果不是则返回undefined
function Emp(name) {
this.name = name
// console.log(new.target)
if (typeof new.target == "undefined") {
throw new Error("必须用new关键字创建对象");
} else {
this.name = name
}
}
Emp() //没有new对象
继承 extends
子类继承父类,可以拿到父类下的属性和方法,减少代码写作
class Father {
constructor() {
this.name = "asd"
}
}
class son extends Father {
}
var a = new son()
console.log(a.name)//asd
super关键字:
super会有两种,一种当关键字用,一种当函数用
注意:当孩子创建自己的构造器,不写super会报错
当成函数来用表示调用父类构造器superclass Father {
constructor(name) {
this.name = name
}
}
class son extends Father {
constructor(name, age) {
super(name)//调用父类构造器 ,当做方法使用
this.age = age
}
}
var a = new son("lisi", 23)写在变量赋值之前,
当成关键字使用,表示的是父类对象,通过对象可以调用父类的属性和方法
class Father {
constructor(name) {
this.name = name
}
foo() {
console.log("父类的函数")
}
}
class son extends Father {
goo() {
console.log(super.name)
super.foo()
}
}
var a = new son("lisi", 23)
a.goo()//父类的函数
set和map
set:类似于数组,用来存储多个值,可以存储多种类型,但是所存储的值是唯一不可重复的,set是对对象体,用构造器赋值,接受一个数组类型
定义:
var s = new Set([1, 2, 3, 4, 5, 5, 5, 1])
遍历:
for(var v of s){
console.log(s)
}
属性和方法
size获取set长度
add()添加元素
deldete()删除元素
has()判断set是否有指定值,返回布尔
clear()清空set值
values()遍历所有value值
keys()遍历所有key值
entries()遍历所有键值对
foreach()遍历set所有值
注意:1.set集合没有索引值和key值,所以遍历出来的都是value,存储不保证有序
2.判断重复,不光值重复,类型也得相同
3.对于对象类型,保证的地址不能重复
var s1 = new Set([1, 2, 3, 4])
s1.add({})
s1.add({})//两个空对象是不同地址,可以存
var obj = {
a: 1,
b: 2
}
s1.add(obj)
s1.add(obj)//两个都是obj对象,地址相同存一个
面试题:
1.数组去重
var a = [1, 2, 3, 4, 5, 4, 3]
// var s = new Set(a)
// arr = [...s]
// console.log(arr) //12345
2.for in 不能遍历es6新数据结构
3.交集,差集,并集
交集
// var a = new Set([1, 2, 3])
// var b = new Set([2, 3, 4])
// var arr = [...a]
// var t = arr.filter(function(index) {
// return b.has(index)
// })
// console.log(t)
// var x = new Set([...a].filter(index => b.has(index)))
//差集
// var arr1 = [...a]
// var t1 = arr1.filter(function(index) {
// return !b.has(index)
// })
// var arr2 = [...b]
// var t2 = arr2.filter(function(index) {
// return !a.has(index)
// })
// var x = [...t2, ...t2]
// console.log(x)
// var x = new Set([...a].filter(index => !b.has(index)))
//var y = new Set([...b].filter(index => !a.has(index)))
//并集
// var s = new Set([...a, ...b])
weakSet集合
weakSet与set类型,保证值不能重复,但是weakset只能存储对象类型,weakset对对象都是弱引用,垃圾回收不用考虑weakSet对对象的引用
定义:
var ws=new weakSet([[1,2],[3,4]])
只能存储引用类型
ws.add(4)//报错,
ws.add({})//可以
对象都是弱引用
var obj={a:1,b:2}
ws.add(obj)
obj=null
console.log(ws)//weakset里的对象没有被清空
属性和方法
add()添加元素
deldete()删除元素
has()判断set是否有指定值,返回布尔
clear()清空set值
map:
map结构类似于Object对象,用键值对存储,是hash结构,但是对象类型的属性只能存储字符串和symbol,map的key值可以为任何类型
定义: var map = new Map([
["name", "lisi"],
[1, true],
[{
s: 2
}, 55]
])
属性和方法:
get(key)获取map的值
set(key,value)获取或修改map值
size()获取map长度
deldete(key)删除map的值
clear()清楚map
keys()遍历所有key值
values()遍历所有value值
entries()遍历所有键值对
foreach()遍历map所有值
has()判断map是否有指定值,返回布尔
注意:
1.map的key和value都可以为任何类型
2.map的key值不能重复,重复则为修改
3.当key存储的基本类型保证值保证值不能重复,当为引用类型时地址不能重复
key相同则修改
// var map = new Map([
// ["name", "lisi"],
// [1, true],
// [{
// s: 2
// }, 55]
// ])
// map.set("name", "张三")
// console.log(map)
key唯一,所以可以存储任何类型
// map.set(undefined, "s")
// map.set(null, "b")
// map.set(NaN, "C")
// console.log(map)
// console.log(map.size)
// console.log(map.get(undefined))//s
// console.log(map.get(null))//b
// console.log(map.get(NaN))//c
对于引用类型,必须保证使用的是同一个地址
// map.set(["a"], "b")
// console.log(map)
// console.log(map.get(["a"]))//undefined 值相同,地址不相同
对于其他类型,只要值严格相同视为一样(===)
// map.set(+0, "a")
// console.log(map.get(-0))//a 视为一个值
map.set(true, "a")
map.set("true", "b")
console.log(map.get(true))//a
// //map转对象
// var map = new Map([
// ["name", "lisi"],
// [1, true],
// ["a", 66]
// ])
// var obj = {}
// for (var [k, v] of map) {
// obj[k] = v
// }
// console.log(obj)
//对象转map
var obj = {
name: "lisi",
true: 22,
aa: 55
}
var map = new Map()
for (var v in obj) {
map.set(v, obj[v])
}
console.log(map)
weakMap
weakMap类似于map,存储的是键值对,weakMap的key值存储的是对象类型,但是不包括null
weakMap的key如果引用了对象,不计入垃圾会使机制
定义
var wm=new weakMap([[{a:44},1],["xx"],true]])
key值只能存储对象类型
wm.set(1,"a")
wm.set(null,"a")//报错
weakMap的key如果引用了对象,不计入垃圾回收垃圾机制
var obj={a:1}
wm.set(obj,"a")
var obj=null
属性和方法:
get(key)获取map的值
set(key,value)获取或修改map值
size()获取map长度
deldete(key)删除map的值
has()判断map是否有指定值,返回布尔值
lterator(遍历器)
在es5所有遍历函数只能遍历数组和集合,不能遍历新增的es6数据结构,所以es6下提供了遍历器的接口,方便我们可以通过,’遍历器访问任何数据类型
作用
1.为所有数据结构提供统一访问机制
2.使数据结构的成员可以按照某种顺序排列
3.通过for of命令直接迭代
可以迭代的数据类型 :Array,Map,set,string,arguments,nodeList(节点对象)
遍历器的原理:
1.创建一个指针对象,指向当前数据结构的起始位置
2.在第一次调用指针对象的next方法,可以将指针指向数据结构的第二个成员,
3.不断的调用next方法会让指针依次寻找下一个成员,
4.在next方法下用value存储每一次遍历的值,用done属性判断遍历是否结束,当值为true则结束
function m(arr) {
var index = 0
return {
next: function() {
return index < arr.length ? {
value: arr[index++],
done: false
} : {
value: undefined,
done: true
}
}
}
}
var it = m(["a", "b", "c", "d"])
console.log(it.next())
console.log(it.next())
console.log(it.next())
//迭代对象
// // function myObjIterator(obj) {
// var arr = Object.keys(obj)//拿到obj的key值
// var index = 0;//定义数组的下标为0
// return {
// next: function() {//创建一个next函数
// return index < arr.length ? {//判断定义的值小于数组长度
// value: obj[arr[index++]],
// done: false
// } : {
// value: undefined,
// done: true
// };
// }
// }
// }
// var obj = myObjIterator({
// a: 1,
// b: 2,
// c: 3
// });
// console.log(obj.next());
// console.log(obj.next());
// console.log(obj.next());
</script>
for和forEach区别
1.for的参数为表达式,foreach的参数为函数体
2.for的循环可以通过break结束,foreach即使写了return也不能停止,只是停止当前循环
forin 和 for of
1.for in遍历数组返回下标,for of遍历数组返回值
2.for in 遍历对象返回key值,for of不能直接遍历对象,需要借助 Object.keys()
3.for in不能遍历set和map, forof则可以
4.for in遍历字符串返回下标,for of遍历字符串返回值
proxy代理器
proxy修改某些操作的默认行为的,类似于"元编程",对编程语言进行编程,proxy是对象的一个拦截
层,对对象的方法进行拦截,处理更安全。
定义\
var obj=new Proxy(对象,限制)
属性和方法:
get(对象,属性,reflect)拦截对象的获取属性
set(对象,属性,reflect)拦截对象的修改属性
apply(目标对象,目标对象上下文,参数数组)拦截对象的apply方法
constructor(对象,参数数组)拦截对象的new命令
definedProperty(对象,属性,权限值)拦截对象的访问权限方法
deleteProperty(对象,属性)拦截对象的delete关键字
has(对象,属性)拦截对象的属性判断(in)
grtOwnPropertyDescriptor(对象,属性)拦截对象的获得原型的方法
isExtensible(对象)拦截对象的判断不可扩展方法
ownkeys(对象)拦截对象的遍历属性方法(拦截全部)
preventExtensions(对象)拦截对象的不可扩展方法
setPrototypeOf(对象)拦截对象的设置原型方法
列如: var obj = new Proxy({
name: "李四",
age: 23
}, {
get: function(obj, key) {
if (key == "age") {
return 18//限制age不能访问
} else {
return obj[key]
}
// console.log("属性被查询了", obj, key)
},
set: function(obj, key, value) {
if (key == "name") {
return obj[key] //限制name不能修改
} else {
obj[key] = value
}
// console.log("属性被修改了", obj, key)
}
})
obj.name = "张三"
obj.age = 2
console.log(obj.name)
console.log(obj.age)
apply:
function sum(a, b) {
return a + b
}
var p = new Proxy(sum, {
//obj目标对象
apply: function(obj, obj1, args) {
console.log("拦截器不让你改")
return Reflect.apply(obj, ...arguments) * 2
}
})
console.log(p(1, 2))
Reflect与proxy一样都操作对象的,Object对象下的方法都在Reflect下做了封装,用来消除
object下的方法的不合理的地方
var obj = {
name: ""
}
try{
var a = Object.defineProperty(obj, "age", {})
}
catch(e){
//自己处理错误
}
var b = Reflect.defineProperty(obj, "age", {})//判断返回的布尔类型值,可操作则为true
3.Reflect把Object下的命令换成了函数体
var obj = {
name: "lisi"
}
console.log("name" in obj) //命令判断
console.log(Reflect.has(obj, "name"))//true//函数判断
4. Reflect的方法与porxy方法一一对应
var obj = {
name: "lisi",
age: 18
}
var p = new Proxy(obj, {
set: function(obj, key, value) {
if (key == "name") {
return Reflect.get(obj, key)
} else {
var a = Reflect.set(obj, key, value)
if (a) {
// obj[key] = value
return Reflect.set(obj, key, value)
}
}
}
})
p.name = "zhangsan"
p.age = 24
console.log(p.name, p.age)