vue js 定义对象_JS标准内置对象Proxy及Vue中的proxy.js文件

昔登铜井望法华,葱茏螺黛浮蒹葭。今登法华望铜井,湖水迷茫烟色瞑。-- 《登法华寺山顶》

Proxy是什么

Proxy是JS标准内置对象中的一个对象。用于创建一个对象的代理。从而实现对对象操作的拦截及自定义,功能类似于Object.defineProperty();

Proxy语法解读

const res = new Proxy(target,handler);
  • target表示要包装的目标对象,可以是任意类型数组,函数,对象...
  • handler通常是一个函数作为属性的对象,比如{get:function(obj,prop){...}}

handler通常有以下几个方法

  • hander.get(target,property,receiver)。target表示目标对象。property表示被获取的属性名。receiver表示Proxy或者继承Proxy的对象。这个方法可以用来拦截属性值得读取操作。
const res = new Proxy({}, {
  get: function(target, prop, receiver) {
    console.log("called: " + prop);
    return 'test';
  }
});

console.log(res.a); // "called: a"
                  // test
  • handler.set(target, property, val)。target表示目标对象。property表示被设置的属性名。val表示新的属性值。这个方法可以用来设置属性值得读取操作。
const res = new Proxy({}, {
  set: function(target, prop, val) {
    target[prop] = val
    return true;
  }
});
res.test = '123'
console.log(res.test);//123

Vue中的proxy.js文件

/* not type checking this file because flow doesn't play well with Proxy */

import config from 'core/config'
import { warn, makeMap } from '../util/index'

let initProxy

if (process.env.NODE_ENV !== 'production') {
  const allowedGlobals = makeMap(
    'Infinity,undefined,NaN,isFinite,isNaN,' +
    'parseFloat,parseInt,decodeURI,decodeURIComponent,encodeURI,encodeURIComponent,' +
    'Math,Number,Date,Array,Object,Boolean,String,RegExp,Map,Set,JSON,Intl,' +
    'require' // for Webpack/Browserify
  )

  const warnNonPresent = (target, key) => {
    warn(
      `Property or method "${key}" is not defined on the instance but ` +
      'referenced during render. Make sure that this property is reactive, ' +
      'either in the data option, or for class-based components, by ' +
      'initializing the property. ' +
      'See: https://vuejs.org/v2/guide/reactivity.html#Declaring-Reactive-Properties.',
      target
    )
  }

  const hasProxy =
    typeof Proxy !== 'undefined' &&
    Proxy.toString().match(/native code/)

  if (hasProxy) {
    const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')
    config.keyCodes = new Proxy(config.keyCodes, {
      set (target, key, value) {
        if (isBuiltInModifier(key)) {
          warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`)
          return false
        } else {
          target[key] = value
          return true
        }
      }
    })
  }

  const hasHandler = {
    has (target, key) {
      const has = key in target
      const isAllowed = allowedGlobals(key) || key.charAt(0) === '_'
      if (!has && !isAllowed) {
        warnNonPresent(target, key)
      }
      return has || !isAllowed
    }
  }

  const getHandler = {
    get (target, key) {
      if (typeof key === 'string' && !(key in target)) {
        warnNonPresent(target, key)
      }
      return target[key]
    }
  }

  initProxy = function initProxy (vm) {
    if (hasProxy) {
      // determine which proxy handler to use
      const options = vm.$options
      const handlers = options.render && options.render._withStripped
        ? getHandler
        : hasHandler
      vm._renderProxy = new Proxy(vm, handlers)
    } else {
      vm._renderProxy = vm
    }
  }
}

export { initProxy }

makeMap()方法。

这个方法创建了一个Map结构,并且返回了一个方法用来检测指定的key是否在这个Map中。

export function makeMap (
  str: string,
  expectsLowerCase?: boolean): (key: string) => true | void {
  const map = Object.create(null)
  const list: Array = str.split(',')for (let i = 0; i     map[list[i]] = true
  }return expectsLowerCase
    ? val => map[val.toLowerCase()]
    : val => map[val]
}

接下来判断浏览器是否支持proxy

const hasProxy =
    typeof Proxy !== 'undefined' &&
    Proxy.toString().match(/native code/)

之后将配置中keycodes做一层代理

const isBuiltInModifier = makeMap('stop,prevent,self,ctrl,shift,alt,meta,exact')
    config.keyCodes = new Proxy(config.keyCodes, {
      set (target, key, value) {
        if (isBuiltInModifier(key)) {
          warn(`Avoid overwriting built-in modifier in config.keyCodes: .${key}`)
          return false
        } else {
          target[key] = value
          return true
        }
      }
    })
  }

之后定义hasHandler和getHandler

const hasHandler = {
    has (target, key) {
      const has = key in target
      const isAllowed = allowedGlobals(key) || key.charAt(0) === '_'
      if (!has && !isAllowed) {
        warnNonPresent(target, key)
      }
      return has || !isAllowed
    }
  }

  const getHandler = {
    get (target, key) {
      if (typeof key === 'string' && !(key in target)) {
        warnNonPresent(target, key)
      }
      return target[key]
    }
  }

最后,定义了initProxy方法。

将vue实例vm作为参数,根据实例的options.render切换了hander,然后有在vm实例上定义了_renderProxy作为vm的代理。

initProxy = function initProxy (vm) {
    if (hasProxy) {
      // determine which proxy handler to use
      const options = vm.$options
      const handlers = options.render && options.render._withStripped
        ? getHandler
        : hasHandler
      vm._renderProxy = new Proxy(vm, handlers)
    } else {
      vm._renderProxy = vm
    }
  }

那么问题来了,options.render是个什么鬼?

明天接着看看吧。

最后说两句

  1. 动一动您的小手,「点个赞吧」
  2. 都看到这里了,不妨  「扫码加个关注」
f60a4fea9963301f4887bc66083da8fc.png
javascript基础知识总结
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值