• 【JavaScript进阶之旅 ES6篇 第十六章】WeakMap跟WeakSet、Proxy、Reflect


    一、内存的生命周期

    1. 分配内存
      ○ C、C++是手动分配内存操作的
      ○ 高级编程语言中:比如JavaScript是自动分配内存
    2. 使用内存
    3. 释放内存
      ○ C、C++是手动释放内存的
      ○ 高级编程语言中:比如JavaScript是垃圾回收机制自动回收引用,释放内存

    二、WeakMap跟WeakSet

    ● 阉割版的Map、Set
    ● 不能遍历(无遍历方法)
    ● 成员必需是对象,否则报错
    ● JS垃圾回收机制不会计数WeakMap跟WeakSet数据类型的引用,不考虑他的引用,是一个弱引用,不需要进入垃圾回收机制即不需要释放内存,所以不可以迭代,他是不可预测的
    ● 不建议使用,因为他是不稳定的
    ● 有很少的特殊的场景,需要使用他

    三、Proxy

    是一个代理模式的实现

    ● let proxy = new Proxy(target, options)

    1、get读取操作

    let star = {
    	name: 'gaoyuanyuan',
    	age: 24,
    	phone: 'gaoyuanyuan188********'
    };
    
    let agent = new Proxy(star, {
    	// 读取操作
    	get: function(target, key) {
    		if(key === 'phone') {
    			return 'agent: 15566655533';
    		}
    
    		if(key === 'price') {
    			return '12k';
    		}
    
    		return target[key];
    	}
    });
    
    console.log(agent.phone); // agent: 15566655533
    console.log(agent.price); // 12k
    console.log(agent.name); // gaoyuanyuan
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    2、set赋值操作

    let star = {
    	name: 'gaoyuanyuan',
    	age: 24,
    	phone: 'gaoyuanyuan188********'
    };
    
    let agent = new Proxy(star, {
    	// 读取操作
    	get: function(target, key) {
    		if(key === 'phone') {
    			return 'agent: 15566655533';
    		}
    
    		if(key === 'price') {
    			return '12k';
    		}
    
    		return target[key];
    	},
    
    	set: function(target, key, value) {
    		if(value < 10000) {
    			throw new Error('价格太低');
    		}else {
    
    			target[key] = value;
    			return true;
    		}
    	},
    });
    
    // agent.coustomPrice = 9000; // index.html:200 Uncaught Error: 价格太低
    
    agent.coustomPrice = 13000;
    console.log(star);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    3、has拦截操作

    ● in操作符会触发has拦截操作
    ● for in循环不会触发has拦截操作

    let star = {
    	name: 'gaoyuanyuan',
    	age: 24,
    	phone: 'gaoyuanyuan188********'
    };
    
    let agent = new Proxy(star, {
    	// 读取操作
    	get: function(target, key) {
    		if(key === 'phone') {
    			return 'agent: 15566655533';
    		}
    
    		if(key === 'price') {
    			return '12k';
    		}
    
    		return target[key];
    	},
    
    	set: function(target, key, value) {
    		if(value < 10000) {
    			throw new Error('价格太低');
    		}else {
    
    			target[key] = value;
    			return true;
    		}
    	},
    
    	has: function(target, key) {
    		console.log('请联系agent:', 15566655533);
    
    		if(key === 'coustomPrice') {
    			return target[key];
    		}else {
    			return false;
    		}
    	}
    });
    
    // agent.coustomPrice = 9000; // index.html:200 Uncaught Error: 价格太低
    
    agent.coustomPrice = 13000;
    console.log(star);
    
    console.log('coustomPrice' in agent); 
    // 请联系agent: 15566655533  
    // true
    
    for(let key in agent) {
    	console.log(agent[key]); // 不会触发has拦截操作
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53

    4、删除代理属性

    let star = {
    	name: 'gaoyuanyuan',
    	age: 24,
    	phone: 'gaoyuanyuan188********'
    };
    
    let agent = new Proxy(star, {
    	// 读取操作
    	get: function(target, key) {
    		if(key === 'phone') {
    			return 'agent: 15566655533';
    		}
    
    		if(key === 'price') {
    			return '12k';
    		}
    
    		return target[key];
    	},
    
    	set: function(target, key, value) {
    		if(value < 10000) {
    			throw new Error('价格太低');
    		}else {
    
    			target[key] = value;
    			return true;
    		}
    	},
    
    	has: function(target, key) {
    		console.log('请联系agent:', 15566655533);
    
    		if(key === 'coustomPrice') {
    			return target[key];
    		}else {
    			return false;
    		}
    	},
    
    	// 拦截删除属性的操作
    	deleteProperty: function(target, key) {
    		if(key.indexOf('_') === 0) {
    			delete target[key];
    		}
    	},
    
    	// 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy) 、Object.keys(proxy),返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys() 的返回结果仅包括目标对象自身的可遍历属性。
    	ownKeys: function(target) {
    
    	}
    });
    
    // agent.coustomPrice = 9000; // index.html:200 Uncaught Error: 价格太低
    
    agent.coustomPrice = 13000;
    console.log(star);
    
    console.log('coustomPrice' in agent); 
    // 请联系agent: 15566655533  
    // true
    
    for(let key in agent) {
    	console.log(agent[key]); // 不会触发has拦截操作
    }
    
    agent._foo = {
    	a: 1
    }
    
    console.log(delete agent._foo);
    console.log(agent);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72

    四、Reflect

    以前通过操作符调用的,在Object下面,现在可以通过函数来调用

    let star = {
    	name: 'gaoyuanyuan',
    	age: 24,
    	phone: 'gaoyuanyuan188********'
    };
    
    console.log(Reflect.get(star, 'name')); // gaoyuanyuan
    
    Reflect.set(star, 'price', '15k');
    console.log(Reflect.has(star, 'price')); // true
    
    console.log('price' in star); // true
    
    // Object构造器上的一些方法都挪到了Reflect上,比如:
    Object.defineProperty(); // 定义一个无法定义的属性会报错
    
    Reflect.defineProperty(); // 定义一个无法定义的属性时候会返回 false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    ● get(target, propKey, receiver); 拦截对象展性的读取,比如 proxy.foo 和 proxy[‘foo’]。
    ● set(target, propKey, value, receiver); 拦截对象展性的设置,比如 proxy.foo=v或 proxy[‘foo’]=v,返回一个布尔值
    ● has(target, propKey); 拦截 propKey in proxy 的操作,返回一个布尔值。
    ● deleteProperty(target, propKey): 拦截 delete proxy [propKey]的操作,返回一个布尔值。
    ● ownKeys(target); 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy) 、Object.keys(proxy),返回一个数组。该方法返回目标对象所有自身的属性的属性名,而 Object.keys() 的返回结果仅包括目标对象自身的可遍历属性。
    ● getOwnPropertyDescriptor(target, propKey); 拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回展性的描述对象。
    ● defineProperty (target, propKey, propDesc); 拦截 Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值
    ●preventExtensions(target); 拦截Object.preventExtensions(proxy), 返回一个布尔值
    ●getPrototypeOf(target); 拦截Object.getPrototypeOf(proxy), 返回一个对象
    ●isExtensible(target); 拦截Object.isExtensible(proxy), 返回一个布尔值
    ●setPrototypeOf(target, proto); 拦截 Object.setPrototypeOf(proxy, proto), 返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
    ●apply(target, object, args); 拦截 Proxy 实例作为函数调用的操作。比如proxy(…args)、proxy.call(object, …args)、proxy.apply(…)
    ●construct(target, args): 拦截 Proxy 实例作为构造函数调用的操作,比如 new proxy(…args)

  • 相关阅读:
    在RockyLinux 9.3环境中采用RPM模式部署Oracle 19C
    redis无法远程连接的所有解决方案大全
    如何做好测试?(五)性能测试(Performance Testing, PT)
    中石油大学22春季《大学英语(四)#》第二阶段在线作业
    windows软件手动设置开机自启
    做一个能对标阿里云的前端APM工具(下)
    LM2904DT运算放大器中文资料规格书PDF数据手册引脚图参数图片功能概述
    【STM32系统】基于STM32设计的按键PWM控制舵机窗帘&柜子&门禁&家居等控制系统——文末资料下载
    xxl-job做集群的时候,用F5做负载均衡效率高还是直接写死几个服务器地址的效率高?
    最优化建模、算法与理论(二)—— 典型优化问题
  • 原文地址:https://blog.csdn.net/Lyb__/article/details/125624592