secrets of the javascript Ninja( with(){} 的用法)(javascript忍者的秘密)

      with语句也是一个功能强大的特性,但是它常常不能被正确的理解。它允许你把一个对象的所有属性放到with语句所指定的作用域中,这样这些属性就可以想平常的JavaScript变量被使用。理解with语句是如何工作的,在你开发中会带来很大的好处。

 

JavaScript中with(){}语句是如何工作的

让我们首先通过一个小例子来看看with(){}语句的基本用法:

var use = "other";
var katana = {
isSharp: true,
use: function(){
this.isSharp = !!this.isSharp;
}
};
with ( katana ) {
//assert( true, "You can still call outside methods." );

isSharp = false;
use();
alert(use!='other');//true
alert(this);//window Object
//assert( use != "other", "Use is a function, from the katana object." );
//assert( this != katana, "this isn't changed - it keeps its original value" );
}
alert(typeof isSharp);//undefined
alert(katana.isSharp);//false 

从这个例子我们来总结一下with的基本用法:

 

1.在with(){}语句中,你可以直接使用with指定的对象的变量和方法。

2.如果外部存在和with指定的对象的变量同名的属性,那么with指定对象中的属性会覆盖其他同名的属性。

3.this指定的是katana的外部作用域。

 

那么我们能否在with(){}语句中添加一些属性和方法呢?来看一段代码:

var katana = {
isSharp: true,
use: function(){
this.isSharp = !!this.isSharp;
}
};
with ( katana ) {
isSharp = false;
cut = function(){
isSharp = false;
};
}
alert(katana.cut);//undefined
alert(cut);

从上面的代码我们可以发现:

 

1.在with语句中只能使用和更改对象已有属性,不能为对象添加新的属性

2.如果为对象添加新的属性,新添加的属性会作为全局对象的属性,而不是with指定对象的属性。

JavaScript中如何使用with(){}语句

我们主要通过一些著名的JavaScript库的示例代码来看看with(){}如何使用:

 

  1. Prototype库中使用with(){}的情况。

Object.extend(String.prototype.escapeHTML, {
div: document.createElement('div'),
text: document.createTextNode('')
});
with (String.prototype.escapeHTML) div.appendChild(text); 

下面是base2库中使用with的情况:

with (document.body.style) {
backgroundRepeat = "no-repeat";
backgroundImage = "url(http://ie7-js.googlecode.com/svn/trunk/lib/blank.gif)";
backgroundAttachment = "fixed";
}

base2中另外的一中情况:

with (document.body.style) {
backgroundRepeat = "no-repeat";
backgroundImage = "url(http://ie7-js.googlecode.com/svn/trunk/lib/blank.gif)";
backgroundAttachment = "fixed";
}
base2中另外的一中情况:
var Rect = Base.extend({
constructor: function(left, top, width, height) {
this.left = left;
this.top = top;
this.width = width;
this.height = height;
this.right = left + width;
this.bottom = top + height;
},
contains: function(x, y) {
with (this) return x >= left && x <= right && y >= top && y <= bottom;
},
toString: function() {
with (this) return [left, top, width, height].join(",");
}
}); 

 

 

Firebug firefox extension中使用with(){}的情况

const evalScriptPre = "with (.vars) { with (.api) { with (.userVars) { with (window) {
const evalScriptPost = "}}}}";
with ( obj ) { with ( window ) { ... } } 

导入命名空间的时候使用如下

YAHOO.util.Event.on(
[YAHOO.util.Dom.get('item'), YAHOO.util.Dom.get('otheritem')],
'click', function(){
YAHOO.util.Dom.setStyle(this,'color','#c00');
}
);
with ( YAHOO.util.Dom ) {
YAHOO.util.Event.on([get('item'), get('otheritem')], 'click', function(){
setStyle(this,'color','#c00');
});

第二个代码是不是简单了很多。

净化面向对象的代码,使用如下方式编写面向对象的代码。

function Ninja(){with(this){
// Private Information
var cloaked = false;
// Public property
this.swings = 0;
// Private Method
function addSwing(){
return ++swings;
}
// Public Methods
this.swingSword = function(){
cloak( false );
return addSwing();
};
this.cloak = function(value){
return value != null ?
cloaked = value :
cloaked;
};
}} 

 

从上面的代码我们可以发现一下三点:

1.私有数据和共有数据是的定义是不一样的

2.由于使用with(this){}使得访问共有数据和私有数据是一样的

3.方法的的定义和变量的定义相似,共有方法必须使用this前缀,但是访问共有方法的时候和私有方法是一样的,由于使用with(this){}

 

 

测试

下面是Scriptaculous test suite.中的一个示例

 

 

new Test.Unit.Runner({
testSliderBasics: function(){with(this){
var slider = new Control.Slider('handle1', 'track1');
assertInstanceOf(Control.Slider, slider);
assertEqual('horizontal', slider.axis);
assertEqual(false, slider.disabled);
assertEqual(0, slider.value);
slider.dispose();
}},
// ...
}); 

 

 

模板

下面来看看John Resig写的一个模板系统:

 

 

(function(){
var cache = {};
this.tmpl = function tmpl(str, data){
// Figure out if we're getting a template, or if we need to
// load the template - and be sure to cache the result.
var fn = !//W/.test(str) ?
cache[str] = cache[str] ||
tmpl(document.getElementById(str).innerHTML) :
// Generate a reusable function that will serve as a template
// generator (and which will be cached).
new Function("obj",
"var p=[],print=function(){p.push.apply(p,arguments);};" +
// Introduce the data as local variables using with(){}
"with(obj){p.push('" +
// Convert the template into pure JavaScript
str
.replace(/[/r/t/n]/g, "")
.split("<%").join("/t")
.replace(/((^|%>)[^/t]*)'/g, "$1/r")
.replace(//t=(.*?)%>/g, "',$1,'")
.split("/t").join("');")
.split("%>").join("p.push('")
.split("/r").join("//'")
+ "');}return p.join('');");
// Provide some basic currying to the user
return data ? fn( data ) : fn;
};
})();
assert( tmpl("Hello, <%= name =>!", {name: "world"}) ==
"Hello, world!", "Do simple variable inclusion." );
var hello = tmpl("Hello, <%= name =>!");
assert( hello({name: "world"}) == "Hello, world!",
"Use a pre-compiled template." ); 

具体解释在此:http://ejohn.org/blog/javascript-micro-templating/

时间: 2024-11-02 02:45:44

secrets of the javascript Ninja( with(){} 的用法)(javascript忍者的秘密)的相关文章

JavaScript数组各种常见用法实例分析_javascript技巧

本文实例讲述了JavaScript数组各种常见用法.分享给大家供大家参考.具体如下: 运行效果如下图所示: 具体代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/x

Javascript中this的用法

this是Javascript语言的一个关键字. 它代表函数运行时,自动生成的一个内部对象,只能在函数内部使用.比如, function test(){ this.x = 1; } 随着函数使用场合的不同,this的值会发生变化.但是有一个总的原则,那就是this指的是,调用函数的那个对象. 下面分四种情况,详细讨论this的用法. 情况一:纯粹的函数调用 这是函数的最通常用法,属于全局性调用,因此this就代表全局对象Global. 请看下面这段代码,它的运行结果是1. function te

JavaScript中exec函数用法实例分析

  本文实例讲述了JavaScript中exec函数用法.分享给大家供大家参考.具体如下: javaScript 中的 exec 函数,用正则表达式模式在字符串中运行查找,并返回包含该查找结果的一个数组. rgExp.exec(str) 参数: rgExp 必选项.包含正则表达式模式和可用标志的正则表达式对象. str 必选项.要在其中执行查找的 String 对象或字符串文字. 说明: 如果 exec 方法没有找到匹配,则它返回 null.如果它找到匹配,则 exec 方法返回一个数组,并且更

javaScript中push函数用法实例分析

  本文实例讲述了javaScript中push函数用法.分享给大家供大家参考.具体分析如下: javaScript 中的 push 方法,将新元素添加到一个数组中,并返回数组的新长度值. arrayObj.push([item1 [item2 [. . . [itemN ]]]]) 参数 arrayObj,必选项.一个 Array 对象. item, item2,. . . itemN, 可选项.该 Array 的新元素. 说明 push 方法将以新元素出现的顺序添加这些元素.如果参数之一为数

javaScript中slice函数用法实例分析

  本文实例讲述了javaScript中slice函数用法.分享给大家供大家参考.具体分析如下: javaScript 中的 slice 函数,对于array对象的slice函数,返回一个数组的一段.(仍为数组) arrayObj.slice(start, [end]) 参数: arrayObj,必选项.一个 Array 对象. start,必选项.arrayObj 中所指定的部分的开始元素是从零开始计算的下标. end,可选项.arrayObj 中所指定的部分的结束元素是从零开始计算的下标.

javaScript中with函数用法实例分析

  本文实例讲述了javaScript中with函数用法.分享给大家供大家参考.具体分析如下: javaScript 中的 with 函数 ,即所谓的with 语句,可以方便地用来引用某个特定对象中已有的属性,但是不能用来给对象添加属性,要给对象创建新的属性,必须明确地引用该对象. with 函数,为语句设定默认对象. with (object) statements 参数: object 新的默认对象. statements 一个或多个语句,object 是该语句的默认对象. 说明: with

JavaScript中String.prototype用法

  本文实例讲述了JavaScript中String.prototype用法.分享给大家供大家参考.具体如下: ? 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 // 返回字符的长度,一个中文算2个 String.prototype.ChineseLength=function() { return this.replace(/[^x00-xff]/g,"**").len

javascript中动态函数用法

  本文实例讲述了javascript中动态函数用法.分享给大家供大家参考.具体分析如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <t

Javascript中With语句用法实例

  本文实例讲述了Javascript中With语句用法.分享给大家供大家参考.具体如下: ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8&qu