关键词:JS、with替代方法
大家好,我是入错行的bug猫。(http://blog.youkuaiyun.com/qq_41399429,谢绝转载)
with
是个好东西,但是大家都在说 不推荐使用
,甚至在严格模式下直接报错!
岂可修呀! (σ;Д)σ死刑!
那么,大家在写JS代码时,有时候不可避免需要使用到with
,使用with
能极大减少代码。
例如:angular
在控制层中变量都绑定到$scope
对象上,但是在视图里面可以直接使用变量名,而省略了$scope
举个栗子
var obj = {
"math":78,
"Chinese":99,
"English":87
}
with(obj){
//mark1
console.log( (math + Chinese + English) / 3 ); //计算并打印平均分,如果没有 with,取变量就会变为 obj.math、obj.Chinese、obj.English
//mark2
}
注意 !(敲黑板),要开始变形了!
去掉with
在 mark1
的地方,假设添加var math = obj.math; var Chinese = obj.Chinese; var English = obj.English;
,把对象属性转化成变量;
那么后续代码也能正常执行;
但是后续代码中,如果给变量math
Chinese
English
重新赋值了,而并没有给obj赋值!!!!!!(所以说JS传参是引用传递还是值传递呢?)
因此,在 mark2
的地方,需要再添加obj.math = math; obj.Chinese = Chinese; obj.English = English;
,变量赋值给对象属性;
再考虑到在 mark1
处申明了很多变量,为了避免与后续作用域中变量冲突,应该将 mark1
mark2
使用代码块包裹起来;
/**
* param [object] 等价于with对象,不能为undefined
* global [object] 函数块中this对象,默认是param
* func [function | string] 等价于with代码块
*/
function catwith ( param, global, func ){
if( !param ) return;
if( typeof(global) == "function" ){
func = global;
global = param;
}
//动态生成 变量声明代码。 _$_$_bugcat_with 是param的形参名,为了避免命名冲突,故意写得很奇葩,越奇葩越好,冲突的概率越小
var head = "\"use strict\";", foot = ";";
for(var key in param){
head = head + "var " + key + " = _$_$_bugcat_with[\"" + key + "\"];";
foot = foot + "_$_$_bugcat_with[\"" + key + "\"] = " + key + ";"
}
head = head + "var $$set = function(key, value){_$_$_bugcat_with[key]=value;};"; //添加内置方法 $$set,在函数块中给param赋值
head = head + "try { ";
foot = "} finally {" + foot + "}";
var funStr = "";
if( typeof(func) === "string" ){
//如果是字符串,直接使用
funStr = func;
} else {
//将with代码块转换成字符串,只保留代码块,去掉多余的字符"function(){}"
funStr = func.toString();
var start = funStr.indexOf("{") + 1, last = funStr.lastIndexOf("}");
funStr = funStr.substring(start, last);
}
//在代码块的前后追加代码声明(mark1),和变量赋值(mark2),生成新的函数。函数的this指向param!!
var nf = new Function("_$_$_bugcat_with", head + funStr + foot).bind(global);
//执行代码块并且返回结果
return nf(param);
}
喜闻乐见的呆毛
var obj = {
"math":78,
"Chinese":99,
"English":87
}
catwith (obj, function(){
console.log( (math + Chinese + English) / 3 );
console.log(this); //打印this,如果是catwith (obj, window function(){..}),那么this即为window
math = 90;
this.name = "bugcat"; //添加属性
$$set("clazz", "csdn"); //添加属性
id = "1"; // 注意!!! id 不存在于obj,被泄露到全局的window了!!!
});
say(obj);
结果
88
{math: 78, Chinese: 99, English: 87}
{math: 90, Chinese: 99, English: 87, name: "bugcat", clazz: "csdn"}
~ the end ~
抵制垃圾信息转载,减少检索时间成本