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/

目录
相关文章
|
8月前
|
JavaScript 前端开发 Serverless
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
Vue.js的介绍、原理、用法、经典案例代码以及注意事项
261 2
|
8月前
|
前端开发 JavaScript 安全
javascript:void(0);用法及常见问题解析
【6月更文挑战第3天】JavaScript 中的 `javascript:void(0)` 用于创建空操作或防止页面跳转。它常见于事件处理程序和超链接的 `href` 属性。然而,现代 web 开发推荐使用 `event.preventDefault()` 替代。使用 `javascript:void(0)` 可能涉及语法错误、微小的性能影响和XSS风险。考虑使用更安全的替代方案,如返回 false 或箭头函数。最佳实践是保持代码清晰、安全和高性能。
454 0
|
5月前
|
数据采集 Web App开发 JavaScript
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
随着互联网的发展,网页数据抓取已成为数据分析和市场调研的关键手段。Puppeteer是一款由Google开发的无头浏览器工具,可在Node.js环境中模拟用户行为,高效抓取网页数据。本文将介绍如何利用Puppeteer的高级功能,通过设置代理IP、User-Agent和Cookies等技术,实现复杂的Web Scraping任务,并提供示例代码,展示如何使用亿牛云的爬虫代理来提高爬虫的成功率。通过合理配置这些参数,开发者可以有效规避目标网站的反爬机制,提升数据抓取效率。
502 4
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
|
3月前
|
JavaScript 前端开发
js中的bind,call,apply方法的区别以及用法
JavaScript中,`bind`、`call`和`apply`均可改变函数的`this`指向并传递参数。其中,`bind`返回一个新函数,不立即执行;`call`和`apply`则立即执行,且`apply`的参数以数组形式传递。三者在改变`this`指向及传参上功能相似,但在执行时机和参数传递方式上有所区别。
45 1
|
3月前
|
JavaScript 前端开发
JS中的构造函数的含义和用法
构造函数是JavaScript中用于创建新对象的特殊函数,通常首字母大写。通过`new`关键字调用构造函数,可以初始化具有相同属性和方法的对象实例,从而实现代码复用。例如,定义一个`Person`构造函数,可以通过传入不同的参数创建多个`Person`对象,每个对象都有自己的属性值。此外,构造函数还可以包含方法,使每个实例都能执行特定的操作。构造函数的静态属性仅能通过构造函数本身访问。ES6引入了`class`语法糖,简化了类的定义和实例化过程。
53 1
|
4月前
|
JavaScript 前端开发
js的math.max的用法
js的math.max的用法
78 6
|
4月前
|
JavaScript 前端开发
JS try catch用法:异常处理
【10月更文挑战第12天】try/catch` 是 JavaScript 中非常重要的一个特性,它可以帮助我们更好地处理程序中的异常情况,提高程序的可靠性和稳定性。
90 1
|
5月前
|
数据采集 存储 JavaScript
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
在现代Web开发中,数据采集尤为重要,尤其在财经领域。本文以“东财股吧”为例,介绍如何使用Puppeteer结合代理IP技术进行高效的数据抓取。Puppeteer是一个强大的Node.js库,支持无头浏览器操作,适用于复杂的数据采集任务。通过设置代理IP、User-Agent及Cookies,可显著提升抓取成功率与效率,并以示例代码展示具体实现过程,为数据分析提供有力支持。
242 2
Puppeteer的高级用法:如何在Node.js中实现复杂的Web Scraping
|
4月前
|
JavaScript
JS中的splice的三种用法(删除,替换,插入)
JS中的splice的三种用法(删除,替换,插入)
358 4
|
5月前
|
JavaScript 前端开发
JavaScript用法
JavaScript用法

热门文章

最新文章

  • 1
    【02】仿站技术之python技术,看完学会再也不用去购买收费工具了-本次找了小影-感觉页面很好看-本次是爬取vue需要用到Puppeteer库用node.js扒一个app下载落地页-包括安卓android下载(简单)-ios苹果plist下载(稍微麻烦一丢丢)-优雅草卓伊凡
    23
  • 2
    Node.js 中实现多任务下载的并发控制策略
    32
  • 3
    【2025优雅草开源计划进行中01】-针对web前端开发初学者使用-优雅草科技官网-纯静态页面html+css+JavaScript可直接下载使用-开源-首页为优雅草吴银满工程师原创-优雅草卓伊凡发布
    25
  • 4
    【JavaScript】深入理解 let、var 和 const
    48
  • 5
    【04】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架二次开发准备工作-以及建立初步后端目录菜单列-优雅草卓伊凡商业项目实战
    44
  • 6
    【03】Java+若依+vue.js技术栈实现钱包积分管理系统项目-若依框架搭建-服务端-后台管理-整体搭建-优雅草卓伊凡商业项目实战
    53
  • 7
    【02】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-ui设计图figmaUI设计准备-figma汉化插件-mysql数据库设计-优雅草卓伊凡商业项目实战
    55
  • 8
    如何通过pm2以cluster模式多进程部署next.js(包括docker下的部署)
    71
  • 9
    【01】Java+若依+vue.js技术栈实现钱包积分管理系统项目-商业级电玩城积分系统商业项目实战-需求改为思维导图-设计数据库-确定基础架构和设计-优雅草卓伊凡商业项目实战
    55
  • 10
    JavaWeb JavaScript ③ JS的流程控制和函数
    62