js

171 阅读5分钟

1. 获取音频的时间长度

地址 www.jianshu.com/p/f1b714f1a…


function getTimes() {
        var obj_file = document.getElementById("upload");
        var content = obj_file.files[0]
        console.log(content)
        //获取录音时长
        var url = URL.createObjectURL(content);
         //经测试,发现audio也可获取视频的时长
        var audioElement = new Audio(url);

        var duration;
        audioElement.addEventListener("loadedmetadata", function (_event) {
            duration = audioElement.duration;
            console.log(duration/60);
        });
    }
    

2.let const var

块级作用域

定义的值都受到{}的限制,外部无法引用{}内部的值,出现在{}里面就是局部变量。但是var只有遇到function才会访问不到,但是let和const遇到{}就会。


var arr =[]
for (var i=0;i<3;i++){
arr.push(function(){
 console.log(i)
})
}
console.log(arr)
arr[0]()
arr[1]()
arr[2]()

// 结果 3 3 3

解决


let arr =[]
for (let i=0;i<3;i++){
arr.push(function(){
 console.log(i)
})
}
console.log(arr)
arr[0]()
arr[1]()
arr[2]()

// 结果 3 3 3

let 和const 不存在变量提升 :在代码中先用在定义var,这样就会输出undefind,但是let或const会报你先使用后声明。

console.log(str)
 var str='zsy'
 //undefined
 console.log(str)
 const str='zsy'
 // Identifier 'str' has already been declared

let const 不能重复申明

暂时性死区

let num =1
{
 console.log(num)
}
//1
let num1 =1
{
 console.log(num1)
 let num1 =2
}
//报错,这个就是暂时性死区,因为里面定义了,就没办法去全局作用域找了

这边得const还有一点,就是不能前面定义后面修改,它定义得是一个常量。


const a=1

//这种时候不能修改

const obj={
    name:'zsy'
}

obj.name ='xiaoxiao'

//这个时候能修改是因为,obj是一个引用对象,所以修改得时候可以修改他的值,不能修改他的地址...

3.原型和原型链以及继承

原型链最主要的就是巧妙的解决了继承的问题。

学习原型和原型链,是因为在js中没有像java里面的类,并且没有办法继承。在ES6里面的class,不是类是一个函数,实际上是语法糖。

例子(这样的链式结构称之为原型链)

在下面这个例子中,son继承了father得方法,当我调用或者打印son本身得时候我们可以看到上面自己得方法learn(),但是drink得方法需要在他的_proto_上面得_proto_去找,这个指向得是他的继承的函数得方法,我们可以用hasOwnProperty方法去检测这个方法在不在某个类上面。

hasOwnProperty

说到这个方法我们也可以在类上面点出来就是因为,再往上找还可以找到object得方法,object.proto 的方法可以使用,在向上找直到_proto_ 的值为null

instanceof

这里的判断类型,就是原型链的知识点了,因为instanceof可以检测出来typeof检测不出来的值,所以用instanceof去检测,在原型链上的方法和对象都可以检测出来true,查看[]的原型链发现最上面也是object,所以 [] instanceof array shi true,这就是说明为什么array是引用对象而不是单独的一种类型。他们都是object对象。要看他的constructor(构造函数)是什么,有的都可以返回true

tips

一个类的 隐式原型===原型对象 既 object.prototype === proto true


class Father{
  constructor(name){
    this.name =name
  }
  drink(){
    console.log('可以喝水')
  }
}
class Son extends  Father{
  constructor(name,subject) {
    super(name)
    this.subject=subject
  }
  learn(){
    console.log('我可以学习')
  }
}
const son = new Son('zsy','前端') 
console.log(son.hasOwnProperty('drink')) 
console.log(son) 
console.log(son instanceof object) 
son.drink()
son.learn()

1657766653862.jpg

4.js底层是什么语言

wenku.baidu.com/view/da98e1…

用得是v8源码,v8得名字来自汽车发动机。

v8得源码在GitHub上面拉得到。v8使用c++写的。

5.js函数中得arguments

因为js不能直接向Java一样实现重载,所以js得argument就可以解决这个问题。(在同一个类中存在过个同名的方法,但是每个方法的参数不同(参数个数和类型))

1.每个函数都有两个内置对象,一个this,一个arguments,它是JS的一个内置对象 .函数内部的类数组对象。因为在js函数对象中传递的形参 可以传也可以不传,若方法里没有写参数却传入了参数,该如何拿到参数呢,答案就是arguments了

arguments对象:函数对象内,自动创建的专门接收所有参数值得类数组对象。

arguments[i]: 获得传入的下标为i的参数值

arguments.length: 获得传入的参数个数!

     // arguments并不能使用数组方法
        function str(a, b) {
            console.log(arguments);
            // 数据类型  object
            console.log(typeof arguments);
                 // 赋值   arguments[0] = "";
            // length长度属性
            console.log(arguments.length);
            // 只能通过length强制将数组拉长
            arguments.length = 15;
            for (var i = 0; i < arguments.length; i++) {
                console.log(arguments[i]);
            }
 
        }
        //赋值实参 
          str("sum", [1, 2, 3, 4, 5, 6, 7, 8, 9], {
            age: 15
        });

2.此外,我们可以看到arguments还有属性callee,length和迭代器Symbol。我们发现callee的值是函数fun,是不是说callee指向函数fun,我们来测试一下


function fun(){
 
// console.log(arguments);
 
console.log('arguments.callee === fun的值:',arguments.callee === fun);
 
}
 
fun('tom',[1,2,3],{name:'Janny'});


// 返回  true

6. symbol

symbol是原始值,不是引用类型

 当一个对象里面有两个同名的值,后面得值,会覆盖前面得值,这个时候用symbol就可以解
 决这个问题,并且这个字段是看不到得。 

 let father={
   son:["sam",'jack'],
   daughter:["amy",'lily','rose'],
   son:["sam"]
 }
 console.log(father)
 
 
 //结果 daughter: (3) ['amy', 'lily', 'rose']
 // son: ['sam']
//   [[Prototype]]: Object

这边是用symbol来覆盖之后


let father={
  son:["sam",'jack'],
  daughter:["amy",'lily','rose']
}
const son = Symbol("sam")
father[son] ="sam"
console.log(father)

//结果 daughter: (3) ['amy', 'lily', 'rose']
// son: (2) ['sam', 'jack']
// Symbol(sam): "sam"
//  [[Prototype]]: Object
 

查看

console.log(Object.getOwnPropertySymbols(father))

//结果 0: Symbol(sam)
// length: 1

Symbol.for

let father={
  son:["sam",'jack'],
  daughter:["amy",'lily','rose']
}
const son = Symbol("sam")
const  anther =Symbol.for('如花')
father[son] ="sam"
father[anther] ="如花的儿子"
console.log(father)

//结果 daughter: (3) ['amy', 'lily', 'rose']
// son: (2) ['sam', 'jack']
// Symbol(sam): "sam"
// Symbol(如花): "如花的儿子"
//  [[Prototype]]: Object

1.symbol函数只可接受一个可选参数,方便后面调试。

2.用object.getOwnPorpertyNames()、object.keys()或者for...in等方法是无法显示symbol属性名

3.object.getOwnPorpertySymbols()方法返回包含所有symbol得属性得数组

4.symbol函数不能使用new关键字,因为是原始值

5.symbol.for 创建共享symbol,如果 已存在,直接返回已有得symbol

6.symbol函数创建得原始值都是唯一得

7.symbol.keyFor()返回已登记得所有键。

链接如果失效看上面得字,都是一样得东西。

image.png

7. babel解析器

将es6语法自动转成es5

8. 闭包

上面let 和const 得例子,用闭包之后。


var arr =[]
for (var i=0;i<3;i++){
  (function (i){
    arr.push(function(){
      console.log(i)
    })
  })(i)
}
console.log(arr)
arr[0]()
arr[1]()
arr[2]()

9. 顶层对象属性 this _globalThis

顶层对象,在浏览器环境中指的得是window对象,在node里面指得是global对象,ES5之中,顶层对象得属性和全局变量是等价得。

window.a =1

// a =1

a=2
window.a =2
// 2

上面得代码顶层对象得属性赋值,与全局变量得赋值是一件事情,是等价的

顶层对象得属性与全局变量得挂钩, 被认为是js语言设计得败笔之一,这样得设计会出现几个大的问题, 1.首先是没办法在编译时就报出变量为申明的错误,只有在运行过程才知道。

2.程序员会不知不觉的就创建了全局变量,比如打错字

3.顶层对象得属性可以是处处可读写得,这非常不利于模块化编程

4.window对象有实体得含义,指的是浏览器得窗口对象,顶层对象是一个有实体含义得对象,也是不合适得。

所以这个在es6就脱钩了,用let 和 const 就解决了。

let ,const 都不属于顶层对象了。

但是var和fun还是属于


var a =1
console.log(window.a)
// 1

let a =1
console.log(window.a)

//undefind

golbalThis 属性

  • 全局环境中,this,会返回顶层对象,但是在node模块和es6模块中,this返回得还是当前得模块
  • 函数里面得this,如果函数不作为对象得方法运行,二十单纯作为函数运行,this回指向顶层对象,但是,严格模式下this回返回undefined

10.模板字符串

语法:

   text:`这里面是模板字符串:
汉皇重色思倾国,御宇多年求不得。
杨家有女初长成,养在深闺人未识。
天生丽质难自弃,一朝选在君王侧。
回眸一笑百媚生,六宫粉黛无颜色。
春寒赐浴华清池,温泉水滑洗凝脂。
侍儿扶起娇无力,始是新承恩泽时。
云鬓花颜金步摇,芙蓉帐暖度春宵。
${pageRequest.current}
${loading}`

11. 对象扩展

1.object.is()

因为在ES5中,比较两个值是否相等,用的总是==或者===去判断,前者忽视类型,后者判断类型,但是这两种都没办法进行单纯的值比较。弥补ES5的缺陷,就用object.is()来比较。

eg:+0 ≠ -0 ,NAN值等于自身

const  a = +0
const  b = -0
console.log(a==b)
//true
console.log(a===b)
//true
console.log(Object.is(a,b))
//false

2.object.assign()

用来合并对象。传入的第一个值是target合并的目标值,将源对象的所有可枚举属性,复制到目标对象中去。

const obj ={}
 let newObj =Object.assign(obj,{a:0},{B:2})
 console.log(obj,'obj')
 //{a: 0, B: 2}  ,obj
 console.log(newObj,'newObj')
//{a: 0, B: 2} 'newObj'
 console.log(Object.is(obj,newObj))
 //true 
 //返回的就是target目标值,所以obj和newObj是完全相同的东西,地址指向完全相同

枚举类

因为在最早创建对象的时候,可以很多选项,可读,可写,可枚举,这里面可枚举就是可以遍历到。

最早用object.denfindPrototype()

枚举类可以被for in遍历到


Object.defineProperty(object,key,{
value:'值',
writable:true,//是否可写
enumerable:true,//是否可枚举
configurable:false, //是否可配置
})

Object.getOwnPropertyDescriptor

可以用这个方法去检测对象中的某个值是不是可枚举的类型

 const obj ={A:2}
 console.log(Object.getOwnPropertyDescriptor(obj,'A'))
 //configurable: true
 //enumerable: true
 //value: 2
// writable: true

3.遍历 键 值 键值对

把键拿出来编程数组 object.keys()

把值拿出来编程数组 object.values()

把键值对拿出来编程数组 object.entries()


let obj ={
      A:1,B:2,C:3,D:4
}
console.log(Object.keys(obj))
    //['A', 'B', 'C', 'D']
console.log(Object.values(obj))
    //[1, 2, 3, 4]
console.log(Object.entries(obj))
    //0: (2) ['A', 1]
    //1: (2) ['B', 2]
    //2: (2) ['C', 3]
    //3: (2) ['D', 4]

12.promise

-首先,promise的出现是为了解决回调地狱,以及终结以前回调+事件,从而让异步的代码用同步的写法

-proimse是异步编程的一种解决方案,比传统的解决方案-回调函数和事件更合理更加的强大,有了promise对象,就可以将异步操作以同步的流程表达出来,为了避免层层嵌套的回调函数,所谓的promise简单来说就是一个容器,里面保存着未来才会结束的事件,通常是一个异步操作的结果

-语法


  let P =new Promise((resolve,reject)=>{
   //里面应该是请求。 jq的写法
  $ajax({
      url:'dizhi',
      success(data){
          console.log(res)
          resolve(data)//保存成功的结果
      }
      error(error){
          reject(error)//保存失败的结果
      }
  }) 
})

p.then(reset =>{
  console.log(res)
}),error(err){
  console.log(err)
}

image.png

三个状态

-pending 初始状态 等待的状态

-fulfilled(以前的)/resolved(现在是这个) 实现操作成功状态

-rejecte 被否决 操作失败的状态

promise的状态一旦改变,成功之后不管.then多少次,永远都是成功的状态,只要后两种出现,状态就凝固的,不会在改变了。

promise.then

promise的then之后的方法,再次.then拿到的是新的proimse。这个值要看上一个.then之后有没有return。是值得话就是值,是引用类型就是promise。要是没有return也是promise


let p =new Promise((resolve, reject) => {
  // 发送请求
  axios.get('/user', {
    params: {
      ID: 12345
    }
  })
    .then(function (response) {
      console.log(response);
    })
    .catch(function (error) {
      console.log(error);
    })
    .then(function () {
      // always executed
    })
})
// .then捕获两个错误
let p2 = p.then(res =>{
  console.log(res)
  return "下一个then的值"
},(err =>{
  console.log(err)
}))
// .then 和.carch 两个分别捕获
p2.then(res=>{
  console.log(res)
}).catch(error =>{
  console.log(error)
})

promise.prototype.then()

成功走得地方

promise.prototype.catch()

失败走的位置

promise.prototype.finally()

就是完成,成功失败都要走得逻辑

在promise里面不管又多少.then,只用些一个catch,一个就可以捕获所有得错误

promise.all

就是把几个promise得实例(就是new出来得promise)以及并发执行,并且将返回成功得数据放在一个数组里面[]。

语法:


let p = promise.all([p1,p2,p3])

image.png

注意

1.返回得结果是全部都成功,会按照成功得顺序返回成功的数据。

2.中间只要有一个失败,整个返回一个失败得错误信息。

promise.race

和all方法很像,但是是谁所有传入得promise谁先改变状态就返回谁。


let p = promise.race([p1,p2,p3])

promise.allSettled

方法接受以promise为实例得数组作为参数,包装成一个新的promise,只有等这些参数所在得promise全部完成请求,并且是成功得才会有返回值。

还有一个promise.try promise.any 现在不知道可以用不

13.Generator (状态机)

Generator函数是Es6新增得一种解决异步编程得方案,语法行为和传统得函数不同。

这个函数有多种理解角度,语法上,可以把它理解成是一个状态机,内部封装了多个内部状态。

运用得地方就在:dva、redux-sage、koa1 库里面。 现在多用async 、await

所以说async、await = Genertor + oc

Generator的语法 :是一个普通的函数,但是有两个特征,一是function关键字和名字之间有一个* 作为连接,二是函数内部使用yieId(产出)表达式,定义内部的不同状态,执行后返回的值是一个遍历器对象,返回的对象上面有一个next方法。


 function * newFun(){
    yield 'hello'
    yield  'new'
    yield  'enen'
    yield  1
    yield  2
  }
 let it = newFun()
  console.log(it.next())
  //{value: 'hello', done: false}
  console.log(it.next())
  //{value: 'new', done: false}
  console.log(it.next())
  //{value: 'enen', done: false}
  console.log(it.next())
  //{value: 1, done: false}
  console.log(it.next())
  //{value: 2, done: false}
  console.log(it.next())
  //{value: undefined, done: true} 

因为传参比较复杂这里面需要拿到上一个next结果给下一个才能用,所以npm上有co库可以简化generator操作。

14.asycn await

这里的asycn、await是generator的语法糖

async function demo(){
   await  1
   await 2
   return 123
}
console.log(demo())
//Promise {<pending>}
let a = demo()
a.then(res =>{
  console.log(res)
}).catch(err=>{
  console.log(err)
})
//123

相对与Genertor的优点

1.内置的执行器 不用再next下去,像co一样内置执行器,不用手动 2.更好的语义 以前的有*,不方便阅读 3.更广的试用性 不用自己手写promise,它自己会转 4.返回值是promise 用起来很简单,直接then或者catch

await也是一个状态机,只有await执行完才能执行下一个代码,await还能执行promise.then方法。当await后面跟的是一个promise就拿promise的值,但是给的是一个对应值,那么就返回一个对应值。


async function demo(){
   let a = await new Promise(resolve => {
       setTimeout(()=>{
          resolve(123)
      },2000)
    })
   let b = await  new Promise(resolve => {
       resolve(a*200)
   })
  return b
 }
 let c = demo()
 c.then(res=>{
   console.log(res)
 }).catch(err=>{
   console.log(err)
 })
 //24600
 

上面这个代码是正确的时候,还有错误的时候就是在a直接返回reject返回的时候。在遇到await后面又一个错误抛出,或者return的时候直接抛出错误,不在执行下面的。但是在没错的时候一定要按照顺序全部执行才返回。

15.函数扩展

1.函数参数默认值

// Es6
 function demo(a=1,b=0){
   return a+b
 }
 console.log(demo())
 //1
 console.log(demo(5))
 //5
 console.log(demo(8,3))
 //11
 // Es5
 function demo(a,b){
   // 这里的0为了避免被认成false 所以用三元判断
   a = a == undefined ? 1 : b
   b = b == undefined ? 0 : b
   return a+b
 }
 console.log(demo())
 //1
 console.log(demo(5))
 //5
 console.log(demo(8,0)
  //8

2....rest

这个rest参数必须在参数的最后一个位置,因为他是获取剩下的所有元素。

3. 严格模式

在Es6现在的规定是,只要函数的参数使用了默认值、解构赋值、或者扩展运算符,那么内部一定不能出现显示设定严格模式,否则报错。(不能用use strict,开启严格模式)原因:函数执行的时候先执行的是函数从参数,然后才是整个函数体,所以不合理会报错。

    const demo = function (...a){
    'use strict';
}

4.name 属性

返回该函数的string函数名

function foo (){

}
console.log(foo.name)
//foo

5.箭头函数

简写

// 箭头函数的简写
// 有返回值的
function demo1 (){
  return 123
}
let demo11 =()=>123
// 无返回值
function demo2 (a,b){
  let absjdh = a+b
}
let demo22 = (a,b) => {}
// 有参数 有返回值
function demo3 (a,b){
  return a+b
}
let demo33 =(a,b)=>a+b
// 无参数 无返回值
function demo4 (){
}
let demo44 =()=> {}
// 没有名字
()=>{}

注意点

  • 箭头函数内没有自己的this,永远指向外部自己定义位置的this,普通函数,在哪调用就是哪里的this。
function demo (){
  console.log(this, '普通函数内部的this')
}
let demo1  = () => {
  console.log(this, '箭头函数内部的this')
}
// demo()
//undefined '普通函数内部的this'
// demo1()
//VueComponent {_uid: 670, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} '箭头函数内部的this'
demo.call({obj:123})
//{obj: 123} '普通函数内部的this'
demo1.call({obj:123})
//VueComponent {_uid: 934, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} '箭头函数内部的this'
let obj ={
    name:123,
    fn:function (){
      console.log(this,"对象内部普通函数内部的this")
    }
}
let obj1 ={
  name:123,
  fn:  ()=>{
    console.log(this,"对象内部普通函数内部的this")
  }
}
obj.fn()
//{name: 123, fn: ƒ} '对象内部普通函数内部的this'
obj1.fn()
//VueComponent {_uid: 390, _isVue: true, $options: {…}, _renderProxy: Proxy, _self: VueComponent, …} '对象内部普通函数内部的this'
  • 箭头函数不可以做构造函数

不可以使用new命令,会报错

  • 不可以使用arguments来获取参数,要用就用...rest参数
  • 不能用作genderator函数

16.class 构造函数

是一个构造函数的语法糖。

//Es5中的构造函数
 function People(a,b,c){
   this.a = a==undefined?0:a
   this.b = b==undefined?0:b
   this.c = c==undefined?0:c

  this.init =function (){
       return this.a+12
   }
  this.run =function (){
     console.log('跑去',this.b)
   }
 }
 let peo =new People(12,'广州',0)
 peo.run()
 //跑去 广州
 console.log(peo)
 //People {a: 12, b: '广州', c: 0, init: ƒ, run: ƒ}
class People{
  constructor(a,b,c) {
    this.a=a
    this.b=b
    this.c=c
  }
  say(){
    console.log('说:',this.a)
  }
}
let peo =new People('我想回家了',1,2)
console.log(peo)
//People {}
peo.say()
//说: 我想回家了

注意事项

  • class内部不能有逗号(,)换行写就可以了
  • 每个class内部都有constructor(){},没有写也会自动生成一个。
  • 并且里面的方法都是放在原型上的,不会多次创建
  • 都是不可枚举的类型。遍历不到。但是可以在原型上找到
  • 实例化的时候一定要有new不然会报错
  • 取值函数getter存值函数setter

构造函数内部的this指向

1.Es6模块中,this指向的是当前的模块。

2.单纯作为函数运行的时候,this会指向顶层的对象,但是在严格模式下,会指向undefined。(解构赋值出来方法,单独调用)

3.如果一个类中的函数不管是通过实例化对象调用还是作为单纯的函数调用都想要它的this指向当前类的实例(当前模块)处理的方法有2种:

  • 在constructor方法中绑定this
  • 使用箭头函数

静态方法

用class 创建的类,里面的方法如果要是静态方法,就在前面加上static来标记,就表示该方法不会被实例继承,而是直接通过类来调用的,这就称之为静态方法

  class Demo {
    static init(){
      console.log('一个用来打印的静态方法')
    }
  }
  Demo.init()
//一个用来打印的静态方法

继承

用关键字,extends就可以。

class Brid {
  constructor(cb,leg) {
    this.cb=cb
    this.leg=leg
  }
  fly(){
    console.log('我有',this.leg,'条腿','我有',this.cb,'翅膀',',我会飞')
  }
}
class Maque extends Brid {}

let mq =new Maque(2,2)
mq.fly()
//我有 2 条腿 我有 2 翅膀 ,我会飞

继承之后有自己单独的东西的时候,继承后的方法里面也有调用父类的值,但是constructor里面不行,super()的作用就是调用父类的constructor()。

class Brid {
  constructor(cb,leg) {
    this.cb=cb
    this.leg=leg
  }
  fly(){
    console.log('我有',this.leg,'条腿','我有',this.cb,'翅膀',',我会飞')
  }
}
class Maque extends Brid {
  constructor(cb,legacy,name,color) {
    super(cb,legacy);
    this.name=name
    this.color=color
  }
  jump(){
    console.log('我可以用',this.leg,'条腿跳','我的名字叫做',this.name)
  }
}
let mq =new Maque(2,2,'lily','red')
mq.fly()
//我有 2 条腿 我有 2 翅膀 ,我会飞
console.log(mq)
//Maque {cb: 2, leg: 2, name: 'lily', color: 'red'}
mq.jump()
//我可以用 2 条腿跳 我的名字叫做 lily

17.call apply bind

都是用来改变this指向的

call 、apply 会调用函数,但是bind不会调用函数。

其中 call和bind第一个参数都是改变this指向的对象,第二个参数依次是传入的参数。bind就是不会直接调用而会返回一个函数,定义之后调用。apply的第二个参数是一个数组的形式。

 function demo(){
   console.log('我的名字',this.name)
 }
 let obj ={
   name:'喵喵'
 }
 demo.call(obj)
 //我的名字 喵喵
 function demo1(food1,food2){
   console.log('我的名字',this.name,',我需要的食物有',food1,food2)
 }
 let obj1 ={
   name:'喵喵'
 }
 demo1.call(obj1,'小鱼干','罐头')
 //我的名字 喵喵 ,我需要的食物有 小鱼干 罐头
 demo1.apply(obj1,['小鱼干','罐头'])
 //我的名字 喵喵 ,我需要的食物有 小鱼干 罐头
let fun  = demo1.bind(obj1,'小鱼干','小肉条')
 fun()
 ////我的名字 喵喵 ,我需要的食物有 小鱼干 罐头

18. Es6模块 exprot和import

出现这种需求是因为,比如像utils这样的通用工具js,不能直接在另一个js里面使用,所有才提出了,模块的导入导出。

  • export和import ES6模块功能主要由两个命令构成:export和import。前者是导出,后者是导入。
export var obj = {}
export var num =12
export { num }
export {num as num2:num} //导出一个num把他名字改成num2导出
import { getRedPacketPoolList } from '../../api/orderServerApi'
import { serchStoreByNameLike } from '../../api/api'

如果要全部导入

import  * as obj from '../../api.api'
  • export_default

这里需要注意的是还有一种,就是默认导出,这个一个js只能出现一个,意思是名字为default的默认模块,在用的时候 improt {这个时候的名字可以随便取} from'' ,用来拿出后面的值。

19.ECMAScript(Webpack)

1.proxy

可以理解成,在目标对象之前架设一层拦截,外界对该对象的访问,都必须通过这层拦截,Proxy用于修改某些操作的默认行为。

  • 语法

    new Proxy(target,handler)

  • 返回值

返回一个对象

  • 现可以拦截13种拦截操作。

a、get(target,propKey,receiver)

b、set(target,propKey,value,receiver)

c、has(target,propKey)

d、deleteProperty(target,propKey)

e、ownKeys(target)

f、getOwnPropertyDescriptor(target,propKey,receiver)

g、defineProperty(target,propKey,receiver)

h、preventExtensions(target)

i、getprototypeof(target)

j、isExtensible(target)

k、setprototypeOf(target,proto)

l、apply(target,object,args)

m、construct(target,args)

链接图片失效的话,图片内容和上面差不多,图片又更加详细的解释。

image.png

image.png

reflect

是一个方法, 把以前object的方法都放在了reflect上面。上面定义了13种方法。

let obj={
  name:'lily',
  age:12
}
let newProxy =new Proxy(obj, {
  get(target,key,receiver) {
    console.log(target,key,receiver)
    //Object 'name' Proxy
    //Proxy {name: 'lily', age: 12}
    return 'zsy' +Reflect.get(target,key,receiver)
  },
  set(target, p, value, receiver) {
    console.log('禁止操作!')
    //禁止操作!
    console.log(target, p, value, receiver)
    //{name: 'lily', age: 12} 'name' 'zsy'
    //Proxy {name: 'lily', age: 12}
    return false
  }
})
console.log(newProxy.name)
//zsylily
console.log(newProxy.age)
//zsy12
newProxy.name ='zsy'
console.log(newProxy.name)