请问如何给函数返回的对象赋值?

bizshow 2008-03-21 08:04:29
我是在ASP中使用JS脚本, 我觉得Recordset用起来不方便,
例如
var connString="..."
var conn=Server.CreateObject("...")
var rs=Server.CreateObject("...")
//每次打开数据库都需要如斯操作:
rs.open(sql,conn,3,3)
Response.Write(rs("...")) // 主要是写 rs("")太麻烦了, 又是括号又是引号
rs.close()

所以我打算写一个RS类, 能够实现
var rs=new RS("select * from ...")
Response.write(rs.id) // 省掉括号引号
rs.execute("select * from ...") //重写execute函数, 若没有关闭连接则先自动关闭

由于JS是引用型语言, 如果是要更新记录
rs.id=1 // 而实际操作并不是更新了记录, 而是把rs.id 这个变量引用到数字1去了
后来我又打算, rs.id 作为只读, 若要更新记录则使用
rs("id")=1 // 原来的方式, 则这个类的默认函数是返回一个字段如斯
function RS(sql){
return function(fieldName){
return rs(fieldName)
}
}

看上去貌似解决了问题, 可是JS是不允许给返回函数赋值的
我又换了另一个想法, 就是
function RS(sql){
rs.id=rs("id")
return rs
}

这样能够解决rs("id")=1的问题, 可是rs.id又不能用了, 不知道怎么搞的,
rs这个对象不能给他赋值,rs.id=rs("id")这句就会提示错误 对象不支持该属性或方法

真搞不懂, 为什么recordset对象既能够
rs("id") 这样像一个函数一样的使用还能给他赋值, 又能够
rs.recordcount 这样像一个属性来使用, 还能够
rs.addNew() 这样像一个方法来使用
而且, rs的属性和方法都可以不区分大小写, 这到底是怎么实现的呢?

下面是代码
function RS(sql, mode){
var rs=null
var field=function(fieldName){
return rs(fieldName)
}
var execute=function(sql,mode){
if(!rs)rs=createRecordset()
if(rs.state!=0){
rs.Close()
field.length=0
}
if(mode==0 || !mode){
rs.open(sql,db,1,1)
rebuildField()
}else if(mode==1){
rs.open(sql,db,1,1)
recycle(rs)
}else if(mode==2){
rs.open(sql,db,1,2)
rebuildField()
}
}
var rebuildField=function(){
if(rs.EOF || rs.BOF)return false
for(var i=0; i<rs.Fields.Count; i++){
switch(rs.Fields(i).Type){
case 3: // Integer
case 11: // Boolean
case 17: // TinyInt
eval("field."+rs(i).Name+'='+rs(i)+'');break;
case 135:
eval("field."+rs(i).Name+'=oDate(rs(i))');break;
case 200:
case 201:
case 202:
case 203:

eval("field."+rs(i).Name+'="'+String(rs(i)).replace(/\\/g,"\\\\").replace(/\"/g,"\\\"")+'"')

break;
}
}
}
field.recordset=rs
execute(sql,mode)
return field
}
...全文
119 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
bizshow 2008-03-24
  • 打赏
  • 举报
回复
我发现SQL Server的好处, 就是不管什么类型的值, 加上单引号都没有问题, 前提是JS能够将值正确的转换为需要的值, 例如
update xxx set xxx='1' 与
update xxx set xxx=1 等效的

但如果 xxx 是 int, 则
update xxx set xxx='aaa' 就会出错
gzdiablo 2008-03-22
  • 打赏
  • 举报
回复
我觉得rs没必要再提供update的能力,只是做做数据映射就够了。映射完数据应该及时关闭rs连接。
update的话直接用execute执行sql就行了
如果rs不及时关闭的话可能带来很多数据连接占用的问题。反而带来了出错的机会。
LZ上面的insert满不错的,但要注意values的单引号问题.
  • 打赏
  • 举报
回复
function RS(sql){
rs.id=rs("id")
return rs
}


这样能够解决rs("id")=1的问题, 可是rs.id又不能用了, 不知道怎么搞的,
rs这个对象不能给他赋值,rs.id=rs("id")这句就会提示错误 对象不支持该属性或方法

这样亏你想得出来,要是支持这个觉得RS对象支持这个属性吗?有这个属性吗?
myvicy 2008-03-21
  • 打赏
  • 举报
回复
你要想改变rs的值就只能对原始的rs进行操作并且在保存之前不能关闭它.
hy_lihuan 2008-03-21
  • 打赏
  • 举报
回复
这个好像和asp语言的内部机制有关吧.没有研究过
yachuan 2008-03-21
  • 打赏
  • 举报
回复
以前看到过一个数据库操作的类。
bizshow 2008-03-21
  • 打赏
  • 举报
回复
还有就是rs的属性和方法不仅仅可以不区分大小写, 甚至于连方法的括号都可以不加.... 这是为什么呢.....?
myvicy 2008-03-21
  • 打赏
  • 举报
回复
^_^
bizshow 2008-03-21
  • 打赏
  • 举报
回复
呵呵, 本人喜欢偷懒, 我甚至还写了一个静态类用于生成一条sql语句, 例如
var field=["ddName","ddClass","ddNickName"]
var valus=["bizshiw","1","布丁"]
var sql = SqlMaker.insert("ddUser", field, valus)
// sql="insert into ddUser(ddName,ddClass,ddNickName) values('...','...','...')"
这样当字段很多的时候, 也不容易出错, 代码维护起来也容易得很多, 可是就是消耗服务器资源, 本来一个字符串能够解决的问题 变成了 N+1个字符串+2个数组
类似的还有给order 部分取反, where部分取反 等等

我有一种想自己开发一个Recordset组件的冲动了, 不知道VB6.0能够开发ActiveX组件吗?
不好意思, 我只会用VB...
myvicy 2008-03-21
  • 打赏
  • 举报
回复
这种方法是不是值得还有待商榷。
个人感觉越是封装只越增加系统的负担降低性能,所减少的仅仅是手头的书写,当然还有一个好处可能是对日后的维护会方便一些。
各有有劣,凭其所好,各选其爱。
bizshow 2008-03-21
  • 打赏
  • 举报
回复
所有对字段的写入, 新增操作都不是实时生效, 只有当调用rs.update()时, 才会将字段的值写入到field对象中并update Recordset

不过这样做性能问题是肯定存在的, 因为每当打开连接或游标移动, 都要重新映射值,
而当数据量非常大, 或则字段中有很长的内容的时候(nText 等类型), 效率肯定会很低下
bizshow 2008-03-21
  • 打赏
  • 举报
回复
哦, 原来如此, 不过我已经封装好了这个类
调用示例:

// 打开记录集, 连接对象在里面已经处理好了, 而且多个实例中是共享的Recordset池, 防止重复的调用CreateObject而没有及时回收加大服务器开销
// 如果有空闲的Recordset对象, 则投入使用, 若没有空闲的, 则自动CreateObject创建一个
var rs=RS("select ddNickName from ddUser", 0) // 最后的参数为0=只读方式打开, 1=一次性调用, 调用结束后关闭连接, 2=可读写方式打开
var a=rs.ddNickName // 这里传的是变量的值, 而不是field的引用, 这样可以避免很多麻烦
//例如 一个Date类型的field对象字段, rs("ddBirthday").getFullYear()这样是错的,
//而 rs.ddBirthday.getFullYear() 则是OK的,
//程序会自动根据字段的类型来重新映射字段的值, 并且类型不会丢失, 当然, 目前只支持各种格式的 数字, 布尔, 字符串 和 日期, 其他格式很少使用, 所以就暂不支持了
rs.moveNext() // 支持游标操作, 如果哪位能够做出不加括号也能调用这个方法, 请告诉我, 非常感谢, 这样就能够像真正的Recordset对象一样

rs.ddNickName="hello" // 赋值操作
rs.update() // update 函数也重写了, 后面的参数是 是否将当前记录作为新的记录来更新

rs.addNew() // 增加新记录操作
rs.ddNickName="world"
rs.update() // 按照常规模式, AddNew是不需要update,可是为了节省编写代码的时间, 所以还是靠update来更新, 而不是在游标移动或者关闭连接时来更新

rs.moveFirst() // 游标操作
for(var i=0; i<rs.length; i++){ // 使用rs.length代替了rs.recordset属性, 一来recordset太长, 二来不符合js的习惯, 例如字符串, 数组等都是length
Response.write(rs.ddNickName+"<br />")
rs.moveNext()
}

rs.moveLast()
while(!rs.bof){ // bof, eof 属性完美的支持
Response.write(rs.ddNickName+"<br />")
rs.moveProv()
}
rs.close()


基本上常用的属性和方法已经重写了, 同时还提供访问真正的Recordset对象的方式, 例如 rs.rs("ddNickName") 来支持没有重写的属性或方法

gzdiablo 2008-03-21
  • 打赏
  • 举报
回复
做映射 数据量大的时候不建议

给些我的代码你参考一下 只是一部分

System.data = {
connection:function(){
var db = Server.MapPath(paths + "bak/abs.mdb");
var conn = Server.CreateObject("ADODB.Connection");
conn.Open("Provider=Microsoft.Jet.OLEDB.4.0;User ID=admin;Data Source=" + db);
return conn;
},
/*
return
Array
{
readonly bool
pageSplit bool
pageSize int
pageIndex int
pageCount int
classType "recordset"
Fields array(string)
}
[item]
Object
{
classType "record"
}
*/
recordSet:function(sql,o){
var options = {
readonly:true,
pageSplit:false,
pageSize:20,
pageIndex:1
}
System.extend(options,o);
var oconn = System.data.connection();
var rs = Server.CreateObject("ADODB.RecordSet");
//System.view(sql,true);

rs.Open(sql,oconn,options.readonly?1:3,options.readonly?1:3);
var arr = [];
var arr1 = [];
options.pageCount = rs.PageCount;
for(var i=0,l=rs.Fields.Count;i<l;i++)
arr1[arr1.length] = rs.Fields.Item(i).Name;
if(!rs.EOF)
{
if(options.pageSplit)
{
rs.PageSize = options.pageSize;
options.pageCount = rs.PageCount;
if(options.pageIndex<1)options.pageIndex = 1;
if(options.pageIndex>rs.PageCount)options.pageIndex = rs.PageCount;
rs.AbsolutePage = options.pageIndex;
}
var pageSize = options.pageSize;
while(!rs.EOF && (!options.pageSplit || pageSize-->0))
{
var obj = {classType:"record"};
for(var i=0,l=arr1.length;i<l;i++)
{
obj[arr1[i]] = rs.Fields.Item(arr1[i]).Value;
switch(typeof(obj[arr1[i]]))
{
case "string":obj[arr1[i]] = String(obj[arr1[i]]);break;
case "boolean":obj[arr1[i]] = RegExp.Cache.booleanTrue.test(new String(obj[arr1[i]]));break;
case "number":obj[arr1[i]] = Number(obj[arr1[i]]);break;
case "date":obj[arr1[i]] = new Date(Date.parse(obj[arr1[i]]));break;
}
}
arr[arr.length] = obj;
rs.MoveNext();
}
}
else
{
for(var i=0,l=rs.Fields.Count;i<l;i++)
arr1[arr1.length] = rs.Fields.Item(i).Name;
options.pageIndex = 0;
}
arr.commandText = sql;
arr.Fields = arr1;
arr.classType = "recordset";
System.extend(arr,options);
rs.Close();
oconn.Close();
return arr;
},
/*boolean*/ execute:function(/*string*/ sql)
{
var oconn = System.data.connection();
var returnvalue = true;
try{
oconn.Execute(sql);
}catch(e){
if(System.debug)
returnvalue = e.message;
else
returnvalue = false;
}
oconn.Close();
return returnvalue;
}
}

myvicy 2008-03-21
  • 打赏
  • 举报
回复
1、是为了安全
2、是为了保密
再如,在浏览器里我们自定义的函数可以通过toString()来看到函数本身的内容,而且我们还可以去更改自定义函数,但是通过toString()我们查看系统函数时得到的是[object],浏览器不让我们看它内部的代码,即便是我们经常用的函数。
myvicy 2008-03-21
  • 打赏
  • 举报
回复
这就是人家为什么是内置的对象.
内部人员有自己固定的行为和方法以及属性,只提供给你使用,不会由你来控制.
而你自己定义的则完全由你来控制.
bizshow 2008-03-21
  • 打赏
  • 举报
回复
还有就是JS中可以给任意对象的未定义的属性赋值
例如
var a=new Object()
a.hello="world"

可是ASP的五大对象也ActiveObject都不能这样, 例如
rs=createObject("...")
rs.hello="world" // 提示对象不支持属性或方法
但是我看了rs的类型, 是继承自object的, 可是为什么这样却不能赋值呢?

搞不懂的...
bizshow 2008-03-21
  • 打赏
  • 举报
回复
其实我就是想不通, 为什么JS要区分大小写,
ASP五大对象不区分大小写, 创建的ActiveObject也可以不区分大小写
调用方法若没参数可以不打括号, 返回函数还可以赋值 等等...

这到底是怎么实现的呢?

87,907

社区成员

发帖
与我相关
我的任务
社区描述
Web 开发 JavaScript
社区管理员
  • JavaScript
  • 无·法
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧