`
achun
  • 浏览: 314228 次
  • 性别: Icon_minigender_1
  • 来自: 河南郑州
社区版块
存档分类
最新评论

无污染的 JavaScript 对象设计

阅读更多

在使用JavaScript构建对象时,出于某种需求要使用prototype(原型定义)设计,

不过这种设计当中有一个讨厌的事情就是Array污染,比如这样定义:

Array.prototype.foo='foo';

 这是一个典型的Array污染,因为所有的Array对象都会继承foo这个成员。这对于习惯用

for (var in [])

这样语法的是个灾难,虽然有方法可以避免,但是这个问题的麻烦还有很多。

现在介绍一种无污染的设计方法:

function array(){};
array.prototype=[];
array.prototype.slice=function(){return this.length;}
var a=new array;
alert('array.slice():'+a.slice());
alert('Array.slice():'+[1,2,3].slice(1));
function object(){};
object.prototype={};
object.prototype.foo=function(){return this.name;}
var o=new object;
o.name='name from new object';
alert('object.foo():'+o.foo());
alert('{foo:"foo"}.foo:'+({foo:"foo"}).foo);

就是这样了,如果你的代码有一些特殊的需要,也许这个方法会有所帮助。

分享到:
评论
22 楼 Relucent 2008-08-26  
indexOf之类的常用方法 还是喜欢直接在Array上追加。

另外 for (var in []) 遍历数组本来就有不少问题,for...in主要用于遍历简单对象的。(当作map用的那种)
21 楼 hax 2008-07-25  
几点:

1. Array、Function、RegExp等是不能被继承的,因为有些特性无法继承(比如内置的[[call]]、[[length]])。

2. Array的污染其实不是很大的问题,因为for in枚举一般是只用于object的,而且是被当作map使用的object。

3. 用Frame得到一个sandbox是个不错的trick,但是跨frame的js行为是存在不确定性的,特别是IE上。
20 楼 csf178 2008-07-16  
笨笨狗 写道
csf178 写道
以前try抛出来个安全异常
现在try了 结果是IE的Array2==Array为true
FF抛异常 麻烦try出来的同学贴个代码看看

且不说这个解决方案严重依赖宿主环境超级无聊
以前试图用这个观察Ucren的函数来的 失败了就没再看过




麻烦你仔细看看上面我给出的链接,然后再自己动手试试看,Dean Edwards大人可不是盖的,这个方法人家用到了Base2库里面……

http://dean.edwards.name/weblog/2006/11/hooray/

// create an <iframe>
var iframe = document.createElement("iframe");
iframe.style.display = "none";
// write a script into the <iframe> and steal its Array object
document.body.appendChild(iframe);
frames[frames.length - 1].document.write("<script>parent.Array2 = Array;<\/script>");


alert(Array2 == Array); // => false
Array2.prototype.each = function(iterator) {  // iterate};
var list1 = new Array(1, 2, 3);
list1.each(print); // => ERROR!
var list2 = new Array2(1, 2, 3);
list2.each(print); // => 1, 2, 3// hooray!


还是那句话,多动手试试……

嗯 不错 果然可以
虽然是小聪明
19 楼 zhxp791008 2008-07-16  
可以使用自定义一个类,对你需要扩展的东东进行包装。
再加入你所需要加入的function或属性.
18 楼 笨笨狗 2008-07-15  
csf178 写道
以前try抛出来个安全异常
现在try了 结果是IE的Array2==Array为true
FF抛异常 麻烦try出来的同学贴个代码看看

且不说这个解决方案严重依赖宿主环境超级无聊
以前试图用这个观察Ucren的函数来的 失败了就没再看过




麻烦你仔细看看上面我给出的链接,然后再自己动手试试看,Dean Edwards大人可不是盖的,这个方法人家用到了Base2库里面……

http://dean.edwards.name/weblog/2006/11/hooray/

// create an <iframe>
var iframe = document.createElement("iframe");
iframe.style.display = "none";
// write a script into the <iframe> and steal its Array object
document.body.appendChild(iframe);
frames[frames.length - 1].document.write("<script>parent.Array2 = Array;<\/script>");


alert(Array2 == Array); // => false
Array2.prototype.each = function(iterator) {  // iterate};
var list1 = new Array(1, 2, 3);
list1.each(print); // => ERROR!
var list2 = new Array2(1, 2, 3);
list2.each(print); // => 1, 2, 3// hooray!


还是那句话,多动手试试……
17 楼 dempire 2008-07-14  
什么都可以污染,就是别污染Object
16 楼 csf178 2008-07-14  
以前try抛出来个安全异常
现在try了 结果是IE的Array2==Array为true
FF抛异常 麻烦try出来的同学贴个代码看看

且不说这个解决方案严重依赖宿主环境超级无聊
以前试图用这个观察Ucren的函数来的 失败了就没再看过
15 楼 achun 2008-07-14  
笨笨狗 写道

这不是我说的,你可以自己去看看Dean Edwards的介绍,或许,你真的没有try就断章取义了?

http://dean.edwards.name/weblog/2006/11/hooray/


在没有自行研究的前提下,不要随便否定别人的观点说法……

嘿嘿,果然早有人用过这种方法,
英文不好,就是不行呀,总要看到中文的解释才会去看,自己搜到了,一大堆英文,自己也很难硬着头皮看.
14 楼 笨笨狗 2008-07-14  
Every JavaScript environment (i.e. a browser window or iframe) has its own copy of the core JavaScript objects and classes. What if we “borrow” one of those objects?
13 楼 笨笨狗 2008-07-14  
csf178 写道
笨笨狗 写道
其实,要解决这个问题,如果你不嫌麻烦,可以在同一个页面上生成一个隐藏的iframe,然后,扩展这个iframe里面的Array对象,并使用它来生产你要的数组实例,这样就能保证你父页面的原型纯净……

但是,就我看来,for..in语句本来就不是专门设计供迭代数组的,而是列举对象可迭代成员的语法,所以,Prototype的设计也是合理的,当然,这是个人观点,其实也是Prototype的设计哲学之一。

这个其实是不允许的 你可以try一下


这不是我说的,你可以自己去看看Dean Edwards的介绍,或许,你真的没有try就断章取义了?

http://dean.edwards.name/weblog/2006/11/hooray/


在没有自行研究的前提下,不要随便否定别人的观点说法……
12 楼 achun 2008-07-14  
我打算放弃了,
因为我发现自己犯了一个显著的错误,
就是JavaScript对非值类型总是引用的(当然也有特例,就是固有对象的prototype成员).
因此我还是不要费这个力气了,还是用常规手段吧.
现有的研究得到的技巧,在使用中灵活运用就行了.
11 楼 csf178 2008-07-14  
<div class='quote_title'>achun 写道</div>
<div class='quote_div'>
<p>偶还是不死心,我试试看能不模式化实例继承(扩展).</p>
<p>其实这个帖子是</p>
<p><a href='../../../../../../topic/214285' target='_blank'>http://www.iteye.com/topic/214285</a></p>
<p> </p>
<p>这个帖子的技术基础,我继续试试有没有模式化实例的方法.</p>
</div>
<p><br/>又稍微看了一下 以前我也研究过类似的 你这东西用来搜索不错 相当于以原型方式高速复制对象</p>
<p>可以代替数组的slice提高搜索效率</p>
10 楼 achun 2008-07-14  
<p>偶还是不死心,我试试看能不模式化实例继承(扩展).</p>
<p>其实这个帖子是</p>
<p><a href='../../../../../../topic/214285' target='_blank'>http://www.iteye.com/topic/214285</a></p>
<p> </p>
<p>这个帖子的技术基础,我继续试试有没有模式化实例的方法.</p>
9 楼 achun 2008-07-14  
csf178 写道
achun 写道
csf178 写道
array的length不正确

我的例子程序是故意写一个错误的slice的.

不是 你这样做其实跟
array.prototype=new Array没什么两样
在IE中 array的实例没法作为真正的数组使用

Function更是如此

还真是有兼容性问题,
看来目前的JavaScript 引擎规范化是个大问题呀!
我一直对用prototype来创建实例,只能创建Object类型感到郁闷,偶然在FF下发现可以创建Array类型(但是不能创建Function类型),就有了这个帖子.


呵呵,还是老老实实的 用实例扩展方法吧.
8 楼 csf178 2008-07-14  
for..in其实就是迭代器 可以针对任何集合使用的
JS1.8还可以改变默认行为迭代range呢
7 楼 csf178 2008-07-14  
achun 写道
笨笨狗 写道
其实,要解决这个问题,如果你不嫌麻烦,可以在同一个页面上生成一个隐藏的iframe,然后,扩展这个iframe里面的Array对象,并使用它来生产你要的数组实例,这样就能保证你父页面的原型纯净……

但是,就我看来,for..in语句本来就不是专门设计供迭代数组的,而是列举对象可迭代成员的语法,所以,Prototype的设计也是合理的,当然,这是个人观点,其实也是Prototype的设计哲学之一。

我的意思是不必对Array,Object的prototype动手,也可以实现类似的prototype,
一般情况下我们常见的构造函数都是生成一个Object实例,我这个方法可以生成Array实例,当然这是javascript本来就支持的,用protorype来生成Array的方法很少见(其实是我从来没有见过),当我发现可以这样写的时候就发了这个帖子,

正确的做法应该是实例继承(这名字是听人说的,其实从这种继承的行为来看也是一种原型继承)
function ArrayEx(){
    var instance=Array.apply(this,arguments);
    instance.myMethod=function(){/*...*/};
    instance.myProperty="any value";
    return instance;
}

像Array这种new与不new一个样的内置对象比较好办 Date的话就要稍微处理一下了
6 楼 csf178 2008-07-14  
achun 写道
csf178 写道
array的length不正确

我的例子程序是故意写一个错误的slice的.

不是 你这样做其实跟
array.prototype=new Array没什么两样
在IE中 array的实例没法作为真正的数组使用

Function更是如此
5 楼 csf178 2008-07-14  
笨笨狗 写道
其实,要解决这个问题,如果你不嫌麻烦,可以在同一个页面上生成一个隐藏的iframe,然后,扩展这个iframe里面的Array对象,并使用它来生产你要的数组实例,这样就能保证你父页面的原型纯净……

但是,就我看来,for..in语句本来就不是专门设计供迭代数组的,而是列举对象可迭代成员的语法,所以,Prototype的设计也是合理的,当然,这是个人观点,其实也是Prototype的设计哲学之一。

这个其实是不允许的 你可以try一下
4 楼 achun 2008-07-14  
笨笨狗 写道
其实,要解决这个问题,如果你不嫌麻烦,可以在同一个页面上生成一个隐藏的iframe,然后,扩展这个iframe里面的Array对象,并使用它来生产你要的数组实例,这样就能保证你父页面的原型纯净……

但是,就我看来,for..in语句本来就不是专门设计供迭代数组的,而是列举对象可迭代成员的语法,所以,Prototype的设计也是合理的,当然,这是个人观点,其实也是Prototype的设计哲学之一。

我的意思是不必对Array,Object的prototype动手,也可以实现类似的prototype,
一般情况下我们常见的构造函数都是生成一个Object实例,我这个方法可以生成Array实例,当然这是javascript本来就支持的,用protorype来生成Array的方法很少见(其实是我从来没有见过),当我发现可以这样写的时候就发了这个帖子,
3 楼 achun 2008-07-14  
csf178 写道
array的length不正确

我的例子程序是故意写一个错误的slice的.

相关推荐

    javascript程序设计教程课件

    JavaScript程序设计教程是深入理解和掌握Web开发核心技术的重要学习资源,尤其对于前端开发人员而言,JavaScript是不可或缺的语言。本教程以项目式教学法展开,旨在帮助学习者通过实践操作来掌握JavaScript的基本...

    Javascript 设计模式系统讲解与应用视频资源地址.7z

    JavaScript设计模式是编程实践中的一种重要思想,它提供了一套经过时间考验的最佳实践,用来解决常见的编程问题和提高代码的可维护性、可扩展性和可复用性。在JavaScript这种动态类型的脚本语言中,设计模式尤其重要...

    JavaScript设计模式与开发实践_himppf_js_jspremise_精通javascript_Js设计模式_

    "函数式编程"也是JavaScript设计模式中的一个重要概念,它鼓励使用无副作用的纯函数和高阶函数,减少代码耦合,提高可读性和可测试性。"柯里化"和"偏函数"是函数式编程中的两种技术,它们可以提升函数的灵活性和重用...

    使用javascript 设计html

    - **变量定义**:JavaScript允许隐式定义变量,即在使用前无需显式声明,但推荐使用`var`、`let`或`const`进行声明,以避免全局变量污染。 - **类型转换**:JavaScript支持自动类型转换,例如数字和字符串之间的转换...

    javascript基础-->中级-->高级-->面向对象

    6. Mixins(混合):通过组合多个组件,实现代码复用,尤其在没有类的JavaScript中,是一种重要的面向对象设计模式。 总结,JavaScript从基础到高级,再到面向对象的深入学习,对于任何参与Web建设的IT人员来说都是...

    JavaScript学习帮助文档_JavaScript学习帮助文档_javascript_

    这份"JavaScript学习帮助文档"是专为初学者设计的,旨在帮助他们掌握JavaScript的基础知识和实际应用技巧。 首先,JavaScript的基本语法是学习的起点。它是一种基于原型的、动态类型的、弱类型的脚本语言。这意味着...

    精通javascript

    2. 原型:每个JavaScript对象都有一个原型(prototype),原型链机制使得对象能继承其他对象的属性和方法。 3. 构造函数与实例化:通过构造函数可以创建具有特定属性和方法的对象实例。 三、闭包 闭包是...

    精通JavaScript与jQuery

    同时,理解JavaScript的作用域和作用域链对于避免变量污染和提升代码质量至关重要。 对于jQuery,重点在于学习如何使用其选择器来选取元素,例如ID选择器、类选择器和属性选择器。还要掌握如何使用jQuery进行DOM...

    DOM Scripting.Web.Design.with.JavaScript.and.the.Document.Object.Model(JavaScript DOM编程艺术)

    9. **网页无障碍性**:强调在使用JavaScript和DOM时,如何考虑网页的无障碍性,使所有用户,包括残障人士,都能方便地使用。 10. **实例应用**:通过实际案例,演示如何将这些知识应用于网页设计和开发,如创建动态...

    javascript特效项目

    9. **AJAX与Fetch API**:用于后台数据的获取和更新,AJAX(异步JavaScript和XML)和Fetch API可以让前端与服务器进行无刷新通信,实现数据的动态加载和更新。 10. **错误处理**:良好的错误处理是项目稳定性的保障...

    JavaScript.Design.Patterns

    JavaScript 设计模式是一种在开发基于JavaScript的应用程序时,遵循的经过验证的最佳实践和解决常见问题的方法。这些模式有助于提高代码的可读性、可维护性和复用性,从而提升整个项目的质量。在JavaScript中,设计...

    javascript

    ### JavaScript核心知识点详解 #### 一、JavaScript简介与特性 **JavaScript**,作为一...无论是基础数据类型的操作,还是面向对象编程的设计模式,JavaScript都提供了丰富的特性和机制,助力开发者实现创新与突破。

    JavaScript快速查询手册.pdf

    JavaScript是一种广泛应用于网页和网络应用的脚本语言,主要由网景公司的Brendan Eich在1995年设计并引入。它被设计用来增强用户的交互体验,通常与HTML和CSS一起使用,构建动态、交互式的网页。JavaScript运行在...

    JavaScript

    它的设计目标是使网页具有交互性、动态性和响应性,最初被命名为LiveScript,但后来为了与Sun Microsystems的Java语言相联系而改名为JavaScript,尽管两者在语法和用途上存在显著差异。 作为一门客户端编程语言,...

    JavaScript核心参考手册

    JavaScript 与Java虽然名字相似,但它们之间并无直接关系,JavaScript更加轻量级,主要应用于浏览器环境,处理DOM(文档对象模型)操作、事件处理、Ajax异步通信等。 手册中可能包括以下几个重要的JavaScript知识点...

    javascript小游戏

    5. **闭包和作用域**:在JavaScript中,合理使用闭包和作用域可以管理函数内部的状态,避免全局变量污染,确保游戏逻辑的正确性。 6. **数据结构与算法**:游戏逻辑往往需要处理各种数据,如得分、生命值等,合理的...

    Javascript特效大全(上册

    这本书可能是JavaScript初学者和进阶开发者提升技能的重要资源,尤其对于那些希望增强网页动态性和用户体验的设计师来说,具有很高的参考价值。 在JavaScript的世界里,特效并不仅仅是炫酷的动画,它们是提升网站...

    Javali创建一个使用ES6Jest的现代JavaScript库

    Javali是一个专为创建现代JavaScript库设计的命令行工具,它借鉴了Create React App的成功模式,为开发者提供了一个快速启动JavaScript库开发的框架。与Create React App主要针对React应用程序不同,Javali关注的是...

    jsdp:JavaScript的设计模式

    在JavaScript中,可以使用闭包来实现单例,避免多次实例化,如全局变量污染和资源浪费。 2. **工厂模式**:抽象创建对象的过程,使得客户端不必关心具体创建哪个类的对象,只需调用工厂函数即可。JavaScript中的new...

Global site tag (gtag.js) - Google Analytics