带有单个字符串的数组会自动且不希望地转换为一个字符串

Array with a single String getting automatically and undesireably converted to just a String

本文关键字:字符串 转换 一个 希望 单个 数组      更新时间:2023-09-26

在我的CasperJS脚本中,当我通过evaluate函数将数组传递给函数时,它可能有1个或多个字符串。当有多个字符串时,它可以按预期工作,但当数组只有一个字符串时它的行为非常奇怪。如果我传递一个数组,其中只有一个字符串,它就变成了字符串。我哪里错了?

我的CasperJS脚本:

function myFunction(input) {
  console.log(JSON.stringify(input));
}
//allow console logs through for debugging
casper.on('remote.message', function(message) {
  this.echo(message);
});
//get my page
casper.start(...);
//attempt to call myFunction with an array as input
casper.then(function() {
  var input = ['#someId'];
  this.evaluate(myFunction, input); 
});

期望输出:

["#someId"]

实际输出:

"#someId"

如果var input=["#firstId","#secondId"],则输出

["#firstId", "#secondId"]

当CasperJS只有两个参数时,这正是它所添加的:函数和函数参数。如果它是一个数组或对象,它将尝试"解压缩"您传递的一个参数:

Casper.prototype.evaluate = function evaluate(fn, context) {
    ...
    // function context
    if (arguments.length === 1) {
        return utils.clone(this.page.evaluate(fn));
    } else if (arguments.length === 2) {
        // check for closure signature if it matches context
        if (utils.isObject(context) && eval(fn).length === Object.keys(context).length) {
            context = utils.objectValues(context);
        } else {
            context = [context];
        }
    } else {
        // phantomjs-style signature
        context = [].slice.call(arguments, 1);
    }
    return utils.clone(this.page.evaluate.apply(this.page, [fn].concat(context)));
};

这导致了有趣的行为,如以下完整的脚本所示:

var casper = require('casper').create();
casper.on("remote.message", function(msg) {
    this.echo("Console: " + msg);
});
casper.start('http://example.com/').then(function(){
    var arr = ['#someId'];
    var arrm = ['#someId', '#someOtherId'];
    var obj = {a:'#someId'};
    var objm = {a:'#someId', b:'#someOtherId'};
    this.echo("1");
    this.evaluate(function(arr) {
        console.log(JSON.stringify(arr));
    }, arr);
    this.echo("2");
    this.evaluate(function(arr) {
        console.log(JSON.stringify(arr));
    }, arrm);
    this.echo("3");
    this.evaluate(function(obj) {
        console.log(JSON.stringify(obj));
    }, obj);
    this.echo("4");
    this.evaluate(function(obj) {
        console.log(JSON.stringify(obj));
    }, objm);
    this.echo("5");
    this.evaluate(function(arr, obj) {
        console.log(JSON.stringify(arr));
        console.log(JSON.stringify(obj));
    }, arr, obj);
    this.echo("6");
    this.evaluate(function(a) {
        console.log(JSON.stringify(a));
    }, obj);
    this.echo("7");
    this.evaluate(function(b) {
        console.log(JSON.stringify(b));
    }, objm);
    this.echo("8");
    this.evaluate(function(a, b) {
        console.log(JSON.stringify(a));
        console.log(JSON.stringify(b));
    }, objm);
    this.echo("9");
    this.evaluate(function(b, a) {
        console.log(JSON.stringify(a));
        console.log(JSON.stringify(b));
    }, objm);
}).run();

输出:

1.控制台:"#someId"2.控制台:["#someId","#someOtherId"]3.控制台:"#someId"4.控制台:{"a":"#someId","b":"#someOtherId"}5.控制台:["#someId"]控制台:{"a":"#someId"}6.控制台:"#someId"7.控制台:{"a":"#someId","b":"#someOtherId"}8.控制台:"#someId"控制台:"#someOtherId"9控制台:"#someOtherId"控制台:"#someId"

请注意,如果对象的键匹配,则会按名称将对象解压缩为evaluate()回调参数(请参见测试8和9)。

PhantomJS本身不进行任何类型的开箱。这都是CasperJS。