javascript - 如何在 JavaScript 中设置动态生成的伪类名称以与 instanceof 运算符一起使用?

标签 javascript function dynamic pseudo-class

我想设置存储在具有特定名称的数组中的 JavaScript 伪类的名称,例如,非数组版本可以完美运行:

var Working = new Array();
Working = new Function('arg', 'this.Arg = arg;');
Working.prototype.constructor = Working;
var instw = new Working('test');
document.write(instw.Arg);
document.write('<BR />');
document.write((instw instanceof Working).toString());

输出:
test
true

但是这种格式不起作用:
// desired name of pseudoclass
var oname = 'Obj';

var objs = new Array();
objs.push(new Function('arg', 'this.Arg = arg;'));

// set objs[0] name - DOESN'T WORK
objs[0].prototype.constructor = oname;

// create new instance of objs[0] - works
var inst = new objs[0]('test');
document.write(inst.Arg);

document.write('<BR />Redundant: ');
// check inst name - this one doesn't need to work
try { document.write((inst instanceof objs[0]).toString()); } catch (ex) { document.write('false'); }
document.write('<BR />Required: ');
// check inst name - this is the desired use of instanceof
try { document.write((inst instanceof Obj).toString()); } catch (ex) { document.write('false'); }

输出:
test
Redundant: true
Required: false

Link to JSFiddle .

最佳答案

就 JS 的流畅性而言,这里发生了一些事情有点不协调(没关系,一旦我离开 4.0 的基本语言特性,我的 C# 就已经很陈旧了)。

首先,我可以建议避免document.write吗?不惜一切代价?
这有技术原因,现在浏览器都在努力规避它们,但它仍然和放置 alert() 一样糟糕。无处不在(包括迭代)。
我们都知道 Windows 系统消息弹出窗口有多烦人。

如果您使用的是 Chrome,请点击 CTRL+Shift+J你会得到一个方便的控制台,你可以console.log()结果进入(甚至对象/数组/函数),它将返回数据集/DOM对象的可遍历节点和其他类型(如函数)的字符串。
当今 JS 的最佳特性之一是您的 IDE 位于浏览器中。
从头开始编写和保存 .js 文件在控制台中并不是特别简单,但测试/调试再简单不过了。

现在,进入真正的问题。

看看你在用示例 #1 做什么。.prototype.constructor的改写应该完全没有必要,除非那里有一些边缘案例浏览器/引擎。

在用作构造函数的任何函数内部(即:使用 new 调用),该函数基本上是在创建一个新对象 {} , 分配给 this , 设置 this.__proto__ = arguments.callee.prototype , 并设置 this.__proto__.constructor = arguments.callee , 其中 arguments.callee === function .

var Working = function () {};
var working = new Working();
console.log(working instanceof Working); // [log:] true
Working不是字符串:你已经把它变成了一个函数。
实际上,在 JS 中,它也是 window 的属性。 (即在浏览器中)。
window.Working    === Working;  // true
window["Working"] === Working; // true

最后一个确实是解决示例 #2 中的困境的关键。

不过,在查看 #2 之前,请注意:
如果你正在做大量的伪子类化,
var Shape = function () {
    this.get_area = function () { };
},

Square = function (w) {
    this.w = w;
    Shape.call(this);
};

如果你想要你的 instanceof要同时使用 Square 和 Shape,那么您必须开始使用原型(prototype)和/或构造函数,具体取决于您想要继承什么以及如何继承。
var Shape = function () {};
Shape.prototype.getArea = function () { return this.length * this.width; };

var Square = function (l) { this.length = l; this.width = l; };
Square.prototype = new Shape();

var Circle = function (r) { this.radius = r; };

Circle.prototype = new Shape();
Circle.prototype.getArea = function () { return 2 * Math.PI * this.radius; };

var circle = new Circle(4),
    square = new Square(4);

circle instanceof Shape; // true
square instanceof Shape; // true

这仅仅是因为我们将原型(prototype)对象(被每个实例重用)设置为父类的全新实例。我们甚至可以在所有子类之间共享该单一实例。
var shape = new Shape();
Circle.prototype = shape;
Square.prototype = shape;

...只是不要覆盖 .getArea ,因为原型(prototype)继承就像继承公共(public)静态方法。

形状当然有 shape.__proto__.constructor === Shape , 和 square.__proto__.constructor === Square 差不多.做一个instanceof只是通过 __proto__ 向上递归链接,检查函数是否与给定的匹配。

如果您以上面列出的方式构建函数( Circle.prototype = new Shape(); Circle.prototype.getArea = function () { /* overriding Shape().getArea() */}; ,那么 circle instanceof Circle && circle instanceof Shape 将自行处理。

混合继承或伪构造函数(返回不是 this 等的对象)需要 constructor mangling,让这些检查工作。

...无论如何...关于#2:

了解以上所有内容,这应该很快就能解决。

您正在为所需的函数名称创建字符串,而不是创建函数本身,并且没有 Obj变量定义,所以你得到一个“引用错误”:相反,让你的“期望名称”成为一个对象的属性。
var classes = {},
    class_name = "Circle",

    constructors = [];


classes[class_name] = function (r) { this.radius = r; };

constructors.push(classes.Circle);

var circle = new constructors[0](8);
circle instanceof classes.Circle;

现在一切都很好地定义了,你不会覆盖任何你不需要覆盖的东西,你仍然可以继承和覆盖 .prototype 的成员, 你仍然可以做 instanceof以程序方式(分配 data.name 作为对象的属性,并将其值设置为 new Function(data.args, data.constructor),并使用该对象属性进行查找)。

希望任何/所有这些都有帮助。

关于javascript - 如何在 JavaScript 中设置动态生成的伪类名称以与 instanceof 运算符一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14914698/

相关文章:

javascript - SetTimeout 后获取返回值

java - 带有自定义对象数组列表的 Java 中的变量范围问题

php - 简单的动态面包屑

javascript - 使用Jquery进行跨域Ajax调用

javascript - php 生成的元素的图像覆盖

c++ - 内联函数在链接期间发生冲突?

c# - 如何在类似于 phpMyAdmin 的 asp.net 中创建动态表/字段

.htaccess RewriteCond REQUEST_URI 动态 SEO 生成的 URI

javascript - 使用属性搜索 json 对象并获取该对象的所有相应属性

javascript - 在 vuetify 中管理 vuelidate 验证