proxy

  • 代理,可以帮我们完成对数据的处理与验证之类的事情,访问对象前添加一层拦截。基本语法let p = new Proxy(target, handler),第一个参数是要用Proxy包装的目标对象(可以使任意类型的对象),第二个参数是一个对象,其属性就是当执行一个操作时定义的代理行为函数。说白了proxy就相当于一个明星的经纪人,我们一般直接联系不到明星吧,我们想要请明星出场就得通过经纪人,下面我们来举例说明。

    let rapStar = {
      name: 'jiangyunsheng',
      age: 24,
      phone: 19888888888
    }
        
    let agent = new Proxy(rapStar, {
      // 取值函数,可以拦截到读取操作
      get (target, key) { 
        if(key === 'phone'){ // 我们一般人是获取不到明星的手机号吧,要联系也是通过经纪人
          return `agent: 1383838438`;
        }
        if(key === 'price'){ // rapStar上并没有这个属性,搞艺术的本身是无价的,但是总归得有出场费吧
          return 300000;
        }
        return target[key]; // 其余不敏感的信息,我们都可以直接获取到
      },
      // 存值函数,可以拦截到赋值操作 
      set (target, key, value) {
        // 经纪人报价,我们要讨价还价的嘛,但也不能太低对不对,如果价格合适,皆大欢喜
        if(value < 200000){
          throw new Error('太低了吧');
        }else{
          target[key] = value;
          return true;
        }
      },
      // 可以拦截到 in 操作符,但是无法拦截 for in 循环的 
      has (targer, key) {
        console.log('详情请联系经纪人: 1383838438')
        if (key === 'customerPrice'){
          return true;
        }else{
          return false
        }
      }
    })
    console.log(); // -> jiangyunsheng
    console.log(agent.phone); // -> agent: 1383838438
    console.log(agent.price); // -> 300000
        
    agent.customerPrice = 250000; // -> 这里我们报价 250000
    console.log(agent.customerPrice); // -> 250000  接受了我们的报价
    // 看看有没有客户报价
    console.log('customerPrice' in agent); // -> true 并打印 详情请联系经纪人: 1383838438复制代码
  • 这只是最基础的应用,其他的大家可以自行摸索,都是一样的用法。

class

  • javascript中只有对象,没有类的概念,是基于原型的面向对象语言。原型对象特点就是讲自身的属性共享给实例化出来的新对象。如果我们要生成一个实例对象,就先需要定义一个构造函数,然后通过new操作符来完成实例。

    function Person (name, age) {
       = name;
      this.age = age;
    }
    Person.prototype.say = function () {
      return 'My name is ' + ;
    }
        
    var p = new Person('zhangsan', 22);
    console.log(p); // -> 下图
    p.say(); // -> My name is zhangsan 
        
    复制代码

       ES6的proxy和class_proxy

  • 这里我们再简单回顾一下构造函数生成实例的过程,当new构造函数时,会隐式的创建一个对象,并把构造函数的作用域给新对象(this -> 新对象),然后执行构造函数内的代码,如果无返回值默认返回新创建出来的对象。

  • 进入正题,ES6引入了class(类)这个概念,实际上就是构造函数的语法糖,写法上注意方法之间不要加逗号,会报错的。

    class Person {
      constructor (name = 'zhangsan', age = 22) { 
        // 实例化的属性配置:私有属性
         = name;
        this.age = age;
      }
      // 公有方法 -> 原型上的方法
      say () {
        console.log(`My name is ${}, ${this.age} years old.`)
      }
    }
    console.log(new Person); // -> 下图
    let p = new Person;
    p.say(); // -> My name is zhangsan, 22 years old.复制代码

       ES6的proxy和class_class_02

  • 二者之间的小区别,类原型上的方法不可枚举。

    function RapStar1 (name) {
       = name;
    }
    RapStar1.prototype.sing = function () {
      console.log(`${}: 遍体鳞伤的人绝不会倒在最艰苦的长征`);
    }
    // 这样也可以在原型上新增方法
    Object.assign(RapStar1.prototype, {
      drink () {
        console.log('一箱啤酒')
      }
    })
    console.log(Object.keys(RapStar1.prototype)); // -> ["sing", "drink"]
        
    class RapStar2 {
      constructor (name) {
         = name;
      }
      sing () {
        console.log(`${}: I just called to tell you drive safe`);
      }
      drink () {
        console.log('whisky');
      }
    }
    console.log(Object.keys(RapStar2.prototype)); // -> []复制代码
  • 当我们没有定义constructor的时候,并不会报错而是会默认为我们定义好一个,只能通过 new 的方式执行。

    class Person {
        
    }
    console.log(new Person);
    Person(); // -> TypeError: Class constructor Person cannot be invoked without 'new'复制代码

       ES6的proxy和class_class_03

  • class不存在变量提升(TDZ),只能先定义再使用,构造函数可以先使用,在定义。

    new C(); // -> ReferenceError: C is not defined
    class C {
        
    }
        
    new B(); // -> B {}
    function B () {
    }复制代码
  • static静态属性,在构造器上新增属性/方法(有兼容性问题,静态方法可以,静态属性低版本会报错),class内部默认启用严格模式。

    class Person {
      static a = 3;
      static say () {
        console.log('hhh');
      }
    }
    console.log(Person.a); // ->  3
    console.log(Person.say()); // -> hhh复制代码
  • 通过extends关键字实现继承,子类必须在constructor方法中调用super方法,否则新建实例时会报错,这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其进行加工,如果不调用super方法,子类就得不到this对象。

    class Father {
      constructor (name= 'foo', money = 100) {
         = name;
        this.money = money;
      }
      say () {
         console.log('hello');
      }
    }
        
    class Son extends Father {
      constructor (name = 'bar') {
        super(name);
      }
    }
    console.log(new Father());
    console.log(new Son());复制代码

       ES6的proxy和class_ES6_04         ES6的proxy和class_class_05

  • super 在对象中使用,可以指代对象的原型。

    let obj = {
      a: 1,
      say () {
        console.log(super.b);
      }
    }
    let proto = {
      b: 2,
      c: 3
    }
        
    Object.setPrototypeOf(obj, proto);
    obj.say(); // -> 2    
    复制代码

总结

  1. class 与 let、const 一样存在TDZ(暂时性死区)
  2. 公有属性不可枚举
  3. 内部默认严格模式
  4. 会默认生成constructor
  5. 只能通过new执行

 ------------------------------------- END -------------------------------------