te')); return $arr; } /* 遍历用户所有主题 * @param $uid 用户ID * @param int $page 页数 * @param int $pagesize 每页记录条数 * @param bool $desc 排序方式 TRUE降序 FALSE升序 * @param string $key 返回的数组用那一列的值作为 key * @param array $col 查询哪些列 */ function thread_tid_find_by_uid($uid, $page = 1, $pagesize = 1000, $desc = TRUE, $key = 'tid', $col = array()) { if (empty($uid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('uid' => $uid), array('tid' => $orderby), $page, $pagesize, $key, $col); return $arr; } // 遍历栏目下tid 支持数组 $fid = array(1,2,3) function thread_tid_find_by_fid($fid, $page = 1, $pagesize = 1000, $desc = TRUE) { if (empty($fid)) return array(); $orderby = TRUE == $desc ? -1 : 1; $arr = thread_tid__find($cond = array('fid' => $fid), array('tid' => $orderby), $page, $pagesize, 'tid', array('tid', 'verify_date')); return $arr; } function thread_tid_delete($tid) { if (empty($tid)) return FALSE; $r = thread_tid__delete(array('tid' => $tid)); return $r; } function thread_tid_count() { $n = thread_tid__count(); return $n; } // 统计用户主题数 大数量下严谨使用非主键统计 function thread_uid_count($uid) { $n = thread_tid__count(array('uid' => $uid)); return $n; } // 统计栏目主题数 大数量下严谨使用非主键统计 function thread_fid_count($fid) { $n = thread_tid__count(array('fid' => $fid)); return $n; } ?>javascript - Can you dynamically add local variables to a function? - Stack Overflow
最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Can you dynamically add local variables to a function? - Stack Overflow

programmeradmin1浏览0评论

I'm using objects to namespace my JavaScript code. These objects usually contain functions that are called mapping the this-pointer to the object itself using apply. However, I find it inconvenient to use the this-pointer everytime I want to access other functions or properties of the object, especially because in lots of cases I use the new-operator to use function-objects the way you would use classes. I would prefer writing new Line() instead if new this.Line().

It would be great if you could add local variables to a function the way php does it with extract (pseudocode following, it's a little more plicated)

var sample_object = {
  "some_function": function() {}
}

test() {
  extract(sample_object);
  some_function();   // imported from sample_object
}

Is that even possible?

I'm using objects to namespace my JavaScript code. These objects usually contain functions that are called mapping the this-pointer to the object itself using apply. However, I find it inconvenient to use the this-pointer everytime I want to access other functions or properties of the object, especially because in lots of cases I use the new-operator to use function-objects the way you would use classes. I would prefer writing new Line() instead if new this.Line().

It would be great if you could add local variables to a function the way php does it with extract (pseudocode following, it's a little more plicated)

var sample_object = {
  "some_function": function() {}
}

test() {
  extract(sample_object);
  some_function();   // imported from sample_object
}

Is that even possible?

Share Improve this question asked Jan 19, 2012 at 20:01 LukasLukas 10.4k17 gold badges82 silver badges128 bronze badges 9
  • 3 You could use a with block, but, I don't suggest it. I also think it's removed in ES5 strict mode. – gen_Eric Commented Jan 19, 2012 at 20:04
  • 1 @Rocket I'd uparrow the not suggesting it part if I could :-) It's true it'd work, but with is confusing and weird. Also I'm pretty sure it causes performance problems but I can't remember the explanation for that. – Pointy Commented Jan 19, 2012 at 20:11
  • What if you pass an array as argument? – elvenbyte Commented Jan 19, 2012 at 20:19
  • @elvenbyte: How would that help? – gen_Eric Commented Jan 19, 2012 at 20:21
  • 2 @Rocket has the answer. with is what you want, though, it is forbidden from ES5 strict mode, and as @Pointy remarks, it does have performance problems: "with forces the specified object to be searched first for all name lookups. Therefore all identifiers that aren't members of the specified object will be found more slowly in a 'with' block. Where performance is important, 'with' should only be used to enpass code blocks that access members of the specified object." (MDN) Other than using with, there's no other way I know of. – rgthree Commented Jan 19, 2012 at 20:24
 |  Show 4 more ments

3 Answers 3

Reset to default 5

I'm pretty sure eval is your only answer; but you need to be aware that if there's any input outside of your control involved, it isn't safe

function dynamicArgs (varName, varValue) {
  eval("var " + varName + "=" + JSON.encode(varValue) );
  alert(a);
}

dynamicArgs("a", "value");

You can see the problem with this. How is your function supposed to call the dynamic variable if it doesn't know its name? I hardcoded it to the a variable since I pass it in when calling it, but that's not a good solution. The only solution would be another eval. You really should think about what you need to do and whether this is useful. But it's doable.

Here it is in action: http://jsfiddle/mendesjuan/GG3Wu/

function dynamicArgs (varName, varValue) {
  eval('var ' + varName + "='" + varValue + "';");
  alert(eval(varName));
}

dynamicArgs("f", "Here I am");

Now here's an example like what you're doing, creating a variable from this.MyConstructor http://jsfiddle/mendesjuan/AK3WD/

var ns = {
    MyConstructor: function(val) {
       this.prop = val;
    },

    runConstructor: function(val) {
      var Ctor = "MyConstructor";
      eval('var ' + Ctor + ' =  this.' + Ctor);
      return new MyConstructor(val);
    }
}


alert( ns.runConstructor("Hello").prop );

And here's an example if you wanted to import all the values from an object into the scope;

http://jsfiddle/mendesjuan/AK3WD/1/

var ns = {
    MyConstructor: function(val) {
       this.val= val;
    },

    anotherProperty: 5,

    runConstructor: function(val) {
        // Bring all the variables from this into this scope
        for (var prop in this) {
            eval('var ' + prop + ' =  this.' + prop);
        }
        alert('Testing var anotherProperty: ' + anotherProperty);
        var obj =  new MyConstructor(val);
        alert('Created MyConstructor: its prop is ' + obj.val)
    }
}


ns.runConstructor("Hello");

There is controversial with, which has some great applications, but is marginally slow and prone to errors. It throws an error in the strict mode (which you should always opt into) and is going to be deprecated.

var sampleObject = {
  someFunction: function() {},
  b: 10
}

with (sampleObject) {
    typeof someFunction // "function"

    var a = 42
    var b = 20
}

sampleObject.a // undefined
sampleObject.b // 20

Note, that new variables defined in a with-block won't be added to the object. Nevertheless, if the object already had an eponymous property in it, this property would be modified (thanks, @Rocket).

Just for fun, here's an implementation of extract using eval (which is even more evil than with). You can do unspeakable things with it, for example if your object has properties like sampleObject['x; while (true) { alert("Hi!") }'].

This is how I did it:

   function smObject ( object) {
    return function () {
        function getter(prop) {
            return function() {
                return this[prop];
            }
        }

        function setter(prop) {
            return function(data) {
                this[prop]=data;
            }
        }

        for (var o = 0; o < object.length; o++) {
            this[object[o]] = {};
            this['get' + object[o]] = getter(object[o]);
            this['set' + object[o]] = setter(object[o]);
        }
    }
}

now you can instantiate a function like this:

var fields = ['Name', 'Id', 'Other', '....' ]
var MyFunction = smObject( fields );
var myObject = new MyFunction();

// getter/setters
myObject.setId(5);
myObject.getId(); // will return 5

Regards, Emanouil

发布评论

评论列表(0)

  1. 暂无评论