为什么 https://gist.github.com/384583 上的 watch() 和 unwatch() 的垫片在 phantomjs 中不起作用?

发布于 2024-11-28 16:56:22 字数 2154 浏览 2 评论 0原文

我正在做一些服务器端 JavaScript 的工作,这些工作本质上既需要访问网站的完整 DOM,又需要跨域打开网站的能力,至少到目前为止,PhantomJS 似乎是完成这项工作的最佳工具。

然而,它缺少一个 Object.watch() 方法,我宁愿拥有它。因此,我尝试使用 Stackoverflow 上其他地方发布的垫片作为答案(可在此处找到: https://gist .github.com/384583)让我可以访问这些方法。

它不起作用。

它也远远超出了我对 JavaScript 的理解水平 - 所以我想知道是否有人可以帮助我准确地理解它在做什么,以及为什么它可能不起作用?

帮助

感谢托比的

(下面引用的代码:

// Cross-browser object.watch and object.unwatch

// object.watch
if (!Object.prototype.watch) {
    Object.prototype.watch = function (prop, handler) {
        var oldval = this[prop], newval = oldval,
        getter = function () {
            return newval;
        },
        setter = function (val) {
            oldval = newval;
            return newval = handler.call(this, prop, oldval, val);
        };
        if (delete this[prop]) { // can't watch constants
            if (Object.defineProperty) { // ECMAScript 5
                Object.defineProperty(this, prop, {
                    get: getter,
                    set: setter,
                    enumerable: true,
                    configurable: true
                });
            } else if (Object.prototype.__defineGetter__ &&     Object.prototype.__defineSetter__) { // legacy
                Object.prototype.__defineGetter__.call(this, prop, getter);
                Object.prototype.__defineSetter__.call(this, prop, setter);
            }
        }
    };
}

// object.unwatch
if (!Object.prototype.unwatch) {
    Object.prototype.unwatch = function (prop) {
        var val = this[prop];
        delete this[prop]; // remove accessors
        this[prop] = val;
    };
}

以及我的测试代码:

tO = {
    "v":0,
    "vplus":function(){this.v ++}
};
tO.watch("v", function(prop, oldval, newval) {
    console.log("The property "+prop+" is now "+tO.v+". Newval is "+newval+" and oldval     "+oldval+".");
    if (newval == 5){phantom.exit()};
});
tO.v = 1;
var i = 0
for(i=0; i<10; i++) {
    tO.v = i; 
    console.log(tO.v);
    if(tO.v == 9){
        console.log("got to 9");
    };
};

I'm doing some server-side javascript bits and pieces that essentially need both access to websites' full DOMs and the ability to open sites cross-domain, and at least so far, PhantomJS seems the best tool for the job.

However, it lacks an Object.watch() method, which I'd rather like to have. As such, I'm trying to use the shim posted as an answer elsewhere on Stackoverflow (available here: https://gist.github.com/384583) to give me access to just such methods.

It isn't working.

It's also well beyond my level of JavaScript understanding - so I'm wondering if anyone could help me understand both exactly what it's doing, and why it might not be working?

Thanks for the help,

Toby

(Code quoted below:

// Cross-browser object.watch and object.unwatch

// object.watch
if (!Object.prototype.watch) {
    Object.prototype.watch = function (prop, handler) {
        var oldval = this[prop], newval = oldval,
        getter = function () {
            return newval;
        },
        setter = function (val) {
            oldval = newval;
            return newval = handler.call(this, prop, oldval, val);
        };
        if (delete this[prop]) { // can't watch constants
            if (Object.defineProperty) { // ECMAScript 5
                Object.defineProperty(this, prop, {
                    get: getter,
                    set: setter,
                    enumerable: true,
                    configurable: true
                });
            } else if (Object.prototype.__defineGetter__ &&     Object.prototype.__defineSetter__) { // legacy
                Object.prototype.__defineGetter__.call(this, prop, getter);
                Object.prototype.__defineSetter__.call(this, prop, setter);
            }
        }
    };
}

// object.unwatch
if (!Object.prototype.unwatch) {
    Object.prototype.unwatch = function (prop) {
        var val = this[prop];
        delete this[prop]; // remove accessors
        this[prop] = val;
    };
}

And my test code:

tO = {
    "v":0,
    "vplus":function(){this.v ++}
};
tO.watch("v", function(prop, oldval, newval) {
    console.log("The property "+prop+" is now "+tO.v+". Newval is "+newval+" and oldval     "+oldval+".");
    if (newval == 5){phantom.exit()};
});
tO.v = 1;
var i = 0
for(i=0; i<10; i++) {
    tO.v = i; 
    console.log(tO.v);
    if(tO.v == 9){
        console.log("got to 9");
    };
};

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

两相知 2024-12-05 16:56:22

回答我自己的问题:提供的垫片似乎将损坏的设置器功能放在适当的位置。特别是,除非处理程序函数返回有意义的内容(很可能不会),否则该属性将设置为未定义。替换

return newval = handler.call(this, prop, oldval, val);

var newval = handler.call(this, prop, oldval, val) || val;
return newval;

似乎可以完成工作。

顺便说一句,这个特殊的填充程序很巧妙,但有一些限制:

  • 依赖监视值的代码可能需要一段时间才能工作,因此最好在关键操作之后更改监视值如果将它们用作标志。

  • 您无法向一个值添加多个处理程序。

To answer my own question: the provided shim seems to put a broken setter function in place. In particular, unless the handler function returns something meaningful (which it may well not), the property gets set to undefined. Replacing

return newval = handler.call(this, prop, oldval, val);

with

var newval = handler.call(this, prop, oldval, val) || val;
return newval;

seemed to do the job.

As a side note, this particular shim is ingenious but includes a couple of limitations:

  • Code relying on a watched value may take a while to work, so it's good to change watched values after critical operations if using them as flags.

  • You can't add multiple handlers to a value.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文