1. 利用proxy浅层冻结,同时不影响原对象
//错误提示文字
const frozenErrStr = "Frozen object is not supported for this function!";

//代理处理器对象
const proxyHandlerObj = {
    //禁止修改value
    set: function(obj, prop, value){
        console.error(frozenErrStr);
        return false;
    },
    //禁止删除key
    deleteProperty: function(target, property){
        console.error(frozenErrStr);
        return false;
    },
    //禁止定义key的属性
    defineProperty: function(target, prop, descriptor){
        console.error(frozenErrStr);
        return false;
    },
    //禁止修改原型链
    setPrototypeOf: function(target, prototype) {
        console.error(frozenErrStr);
        return false;
    },
    //禁止使用preventExtensions将对象改为不可扩展
    preventExtensions(target) {
        console.error(frozenErrStr);
        return false;
    }
};
//返回一个禁止修改直接属性的代理对象
const frozenObjProxy = targetObj => {
	return new Proxy(targetObj,proxyHandlerObj);
}
  1. 利用proxy递归冻结,同时不影响原对象
function frozenObjFn (obj) {
	const cache = new WeakMap();//用于缓存冻结的对象
	return new Proxy(obj,Object.assign({
		//修改get,使获得的对象也被冻结
		get: function(target, property, receiver) {
			const val = target[property];
			if(typeof target[property] === 'object'){
				//冻结对象中的对象并缓存
				if (!cache.has(val)) {
					cache.set(val, frozenObjFn(val));
				}
				return cache.get(val);
			}else{
				//非对象正常返回
				return val;
			}
		}
	}, proxyHandlerObj));//proxyHandlerObj复用上面的并结合get
}
  1. 返回一个禁止改变this引用的代理
const frozenThisFn = target => {
	const cache = new WeakMap();//用于缓存bind后的函数
	const handler = {
		get (target, key) {
			const value = Reflect.get(target, key);
			if (typeof value !== 'function') {
				return value;
			}
			if (!cache.has(value)) {
				//强制绑定this为target并缓存绑定后的函数
				cache.set(value, value.bind(target));
			}
			return cache.get(value);
		}
	};
	return new Proxy(target, handler);
}
  1. 返回一个无法获取set开头函数的代理
const frozenSetFn = target => {
	const handler = {
		get (target, key) {
			//当key以set开头且value为函数时返回错误值
			if(key.startsWith("set") && typeof Reflect.get(target, key) === 'function') {
				console.error(frozenErrStr);
				return frozenErrFn;
			}
			return value;
		}
	};
	return new Proxy(target, handler);
}
  1. 利用freeze深冻结原对象
/**递归冻结对象*/
function deepFreeze(o) {
	let prop, propKey;
	// 首先冻结第一层对象
	Object.freeze(o) ;
	for (propKey in o) {
		prop = o[propKey];
		if (!o.hasOwnProperty(propKey) || !(typeof prop === "object") || Object.isFrozen(prop)) {
			// 跳过原型链上的属性、基本类型和已冻结的对象.
			continue;
		}
		//递归调用
		deepFreeze(prop) ;
	}
}
03-08 17:33