【JS小技巧】JavaScript 函数用作对象的隐藏问题

用户反馈

@消失的键盘 在论坛反馈了一个问题,在 AppBoxMvc 中的 Title 模型中,如果将 Name 属性改名为小写的 name 属性,就会报错:

因为这是一个 ASP.NET MVC 的项目,而这个属性是通过 TextBoxFor 渲染到页面上的,因此 name 会生成为 DOM 节点的 id 属性:

F.SimpleForm()
                .ID("SimpleForm1")
                .ShowBorder(false)
                .ShowHeader(false)
                .BodyPadding(10)
                .Items(
                    F.TextBoxFor(m => m.name),
                    F.TextAreaFor(m => m.Remark)
                )

按道理说这也没什么,虽然有点别扭,但是也没有规定说name字符串不能作为id属性的值。

并且从另一个方面讲,name 也不是 JavaScript 的关键字,不可能冲突阿。

分析问题

还是从代码入手,经过简单的调试,发现 id=name 的这个文本输入框对象居然找不到,而这个对象是保存在 F.ui 上面的。

首先我们看下 F.ui 的定义:

F.ui = function(item) {
    var itemType = F.getType(item.type || ‘component‘);
    return new itemType(item);
};

为了方便用户书写代码,FineUIMvc中 F.ui 其实有两个用途:

1. 用作函数:创建控件,可以在JS中通过 F.ui 来创建一个控件:

F.ui({
        type: ‘button‘, renderTo: document.body, text: ‘按钮‘, id:‘button1‘,
        listeners: {
                click: function (event) {
                        F.alert(‘你点击了按钮‘);
                }
        }
});

2. 用作对象:保存控件,可以在JS中通过 F.ui 来引用一个控件(比如上面创建的按钮):

F.ui.button1

这样一分析问题就来了,因为本身JS函数是有属性的,这里由于 F.ui 是个匿名函数,所以 F.ui.name == ‘‘ (这个函数的 name 属性为空字符串)

对于一个普通的函数,这个name属性就是函数名称,如下所示:

function test1() { }
console.log(test1.name)  // "test1"

其实JavaScript 函数不仅有 name 属性,还是 length , caller, arguments, toString .... 等很多属性,在Chrome的调试工具中可以方便的查看:

所以,当我们试图将名为 name 的文本输入框对象保存到 F.ui 上时,其实是不成功的,此时 F.ui.name 依然为空字符串。

解决问题

由于 F.ui 的两个作用已经被网友所熟知,并且已经应用到很多项目中了,不能因为几个特殊属性的冲突就废弃这种做法。那么怎么规避这个问题呢?

我们使用了一个内部变量来保存页面上的控件实例:

F._fjs_objects = {};

同时为了兼容之前的代码,F.ui 函数仍然用来保存控件实例,只不过在保存之前要先进行判断,如果传入的名称是函数属性名的话,就不要保存:

function nameIsPropertyOfFunction(name) {
    return $.inArray(name, [‘arguments‘, ‘caller‘, ‘length‘, ‘name‘]) >=0 || $.isFunction(F.ui[name]);
}

F._fjs_addToFObjects = function(objId, obj) {
    F._fjs_objects[objId] = obj;

    if(!nameIsPropertyOfFunction(objId)) {
        F.ui[objId] = obj;
    }
};

优化后,之前的所有代码都不用改动,你仍然可以通过两种方式获取控件实例:

1. F(‘controlid‘)
2. F.ui.controlid

而对于非常特殊的情况,控件ID为 name, length, toString (当然我们极力不推荐你用这样的名称来命名控件ID!!)时,页面也不会出错,只不过你不能再通过F.ui.name 来获取控件了,只能通过 F(‘name‘) 来获取控件对象。

时间: 2024-12-15 01:34:29

【JS小技巧】JavaScript 函数用作对象的隐藏问题的相关文章

JavaScript函数和对象提高!!!!!!

JavaScript函数和对象提高!!!!!! 主要内容介绍 函数 函数的概念 函数的参数 函数的返回值 函数的作用域 变量提升和函数提升 函数参数传递方式 对象 什么是JavaScript对象 创建对象的两种方式 对象属性的基本操作 创建自定义对象 函数的4种调用方式(简单介绍) 一.函数 函数小测验 函数复习测试题 1.1 函数基本概念 1.1.1 什么是函数 函数是定义一次但可以调用或执行任意多次的一段JavaScript代码. 函数也叫做方法(了解概念) 当一个函数在一个对象上被调用的时

漫话javascript函数与对象的关系

javascript函数与对象的关系 一直觉得红宝书中的一句话特别经典"函数是对象,函数名是引用",揭示了函数就是对象的本质: 在javascirpt中有一类数据类型,我们通常称之为简单的数据类型,包含了常见的数字(Number),字符串(String),布尔值(true,false),以及常常让人难以琢磨和始料未及的null,undefined:除了这些之外的其他所有值我们都可以成为对象,虽然上述的几种简单的数据类型拥有方法或属性:但是他们不是可变的:在<javascript语

JS小技巧大本事(持续更新)

1. 复制N个字符 1 String.prototype.repeat = function(num){ 2 return (new Array(++num)).join(this); 3 } 4 5 var a = 'A'; 6 a.repeat(5); //'AAAAA' 2. 替代if…else… 1 var result; 2 3 result = isTrue ? something : anotherthing; 4 result = something || anotherthin

js小技巧: 给div绑定keydown事件

要想给一个元素绑定keydown事件我们经常这样: $('#some_thing').keydown(function(event){ ...... }) 但是当你尝试给div元素绑定时会发现不起作用, 解决办法是给这个div添加一个tabindex的属性: $('#some_div').attr('tabindex', 1).keydown(function(event){ ...... }) js小技巧: 给div绑定keydown事件

javascript小技巧-js小技巧收集(转)

本文转载自:http://blog.csdn.net/ocean20/article/details/2498699 每一项都是js中的小技巧,但十分的实用! 1.document.write(""); 输出语句 2.JS中的注释为// 3.传统的HTML文档顺序是:document->html->(head,body) 4.一个浏览器窗口中的DOM顺序是:window->(navigator,screen,history,location,document) 5.得

javascript 函数与对象

javascript中的函数是非常重要的概念,也是比较难于理解的一个知识点! 下面就来聊聊函数: JS基于对象:什么是基于对象呢?简单的说所有代码都是"对象"; 比如函数: function person(){ } person();//1 调用函数; 比如变量: var  x=5; x=6     // 2 重新为x赋值; 上面的函数和变量都是对象:所有的函数都是Function类的对象,x是Number类的对象.相当于 var x=new Number(5): 注意: functi

2015第37周五javascript函数arguments对象巧用一

Javascript函数的一个巧妙利用:假定action中有一个JSONObject类型的对象data,其值有可能为空,则前台JSP页面的JS代码中想直接通过EL表达式,即${data}的形式访问对象的值,则可能会因为data对象为空导致JS预处理错误,如JSP中有这样的代码,var obj=${data};,则当后台data为null时前台页面会变成var obj=;进而页面报错终止运行.有人想通过类似 var obj=('${data}'==''?{}:${data})来解决,但该代码依旧编

javascript 函数2——对象排序

<!DOCTYPE html> <html> <head> <title>javascript排序</title> <meta charset="UTF-8"> </head> <body> <div id="person"></div> <script type="text/javascript"> // //根据

js小技巧--摘录1

原文地址https://github.com/loverajoel/jstips 1.数组中插入元素 a.尾部追加 var arr = [1,2,3,4,5]; var arr2 = []; arr.push(6); arr[arr.length] = 6; arr2 = arr.concat([6]); //快慢排序1. arr[arr.length] = 6; // 平均42 345 449 ops/sec 2. arr.push(6); // 慢34.66% 3. arr2 = arr.c