如何使用JavaScript';s新运算符是否定义为函数?
如果JavaScript如何使用JavaScript';s新运算符是否定义为函数?,javascript,Javascript,如果JavaScriptnew操作符是一个函数,它将如何定义 function _new(fn) { // What goes here? } 仇恨者会憎恨的,但像这样的事情 显然,这只是new的一个循环别名,但可以通过参数扩展它的潜力 由于用户代码的功能,有一些限制:本机构造函数,如newdate和newregexp和绑定函数,无法使用此函数正确填充 如果您正在查找相关的规范部分,它们是和 不管怎样,下面是: // we're assuming that correct argum
new
操作符是一个函数,它将如何定义
function _new(fn) {
// What goes here?
}
仇恨者会憎恨的,但像这样的事情 显然,这只是
new
的一个循环别名,但可以通过参数扩展它的潜力
由于用户代码的功能,有一些限制:本机构造函数,如
newdate
和newregexp
和绑定函数,无法使用此函数正确填充
如果您正在查找相关的规范部分,它们是和
不管怎样,下面是:
// we're assuming that correct arguments are given
function _new(F, args) {
// we could have host objects, make sure edge case not left out
// (typeof could be other than object or function in this case - see bottom)
function Type(arg) {
if (arg === undefined) return 'Undefined';
if (arg === null) return 'Null';
if (arg === false || arg === true) return 'Boolean';
var type = typeof arg;
if (type === 'string') return 'String';
if (type === 'number') return 'Number';
return 'Object';
}
// 1. Let obj be a newly created native ECMAScript object.
// 2. Set all the internal methods of obj as specified in 8.12.
// 3. Set the [[Class]] internal property of obj to "Object".
// 4. Set the [[Extensible]] internal property of obj to true.
// All of the steps above are implicitly completed in steps 6 or 7
var obj;
// 5. Let proto be the value of calling the [[Get]] internal property of F
// with argument "prototype".
var proto = F.prototype;
// 6. If Type(proto) is Object, set the [[Prototype]] internal property of
// obj to proto.
if (Type(proto) === 'Object') obj = Object.create(proto);
// 7. If Type(proto) is not Object, set the [[Prototype]] internal property
// of obj to the standard built-in Object prototype object as described
// in 15.2.4.
else obj = {};
// 8. Let result be the result of calling the [[Call]] internal property of
// F, providing obj as the this value and providing the argument list
// passed into [[Construct]] as args.
var result = F.apply(obj, args);
// 9. If Type(result) is Object then return result.
if (Type(result) === 'Object') return result;
// 10. Return obj.
return obj;
}
关于typeof
案例,即当宿主对象返回一个typeof
值时的边缘案例,该值不是object
或function
。通过测试它们不可能是的任何东西,这允许我们正确地测试它,而不是依赖它们作为本机对象
请注意,这至少适用于ES5——填充
对象的唯一方法。在ES3或更旧的环境中创建将使用我们当前正试图模拟的东西,这会破坏这样做的目的。这似乎是最低限度的必要条件,尽管不是100%符合语言定义,也没有错误检查。只有ES5。对象有一个垫片。create
,但它必须调用new
,这在上下文中是毫无意义的
function _new(T, args) {
var o = Object.create(T.prototype);
var res = o.constructor.apply(o, args);
return (typeof res === 'object') ? res : o;
}
使用方法:
function A(name) {
this.name = name;
}
A.prototype.hello = function() {
console.log(this);
}
var foo = _new(A, ['foo']);
var bar = _new(A, ['bar']);
console.log(foo.name);
console.log(bar.name);
调用构造函数的返回值测试是必要的,因为构造函数不必返回此
——如果构造函数不返回任何内容,则此
是隐式的
看最近也有同样的好奇心
有些步骤是内部任务,无法在语言中重新实现
而且,在我的文章中,澳航在使用typeof
作为仿Type()
但是,有了这些,这是我能做到的最接近的了。尽管如此,它仍然需要可用(因此,ES5+)
例如:
function Foo(one, two) {
this.one = one;
this.two = two;
}
var bar = Object.new(Foo, 'a', 'b');
console.log(bar instanceof Foo); // true
console.log(bar.one); // "a"
console.log(bar.two); // "b"
以及注释版本,包括和中的步骤:
@raam86不,是接线员!这实际上是一个很好的问题……这个问题离题了,因为它不实用。new
运算符是该语言的一部分。使用它。没有理由重新实现它。@RaymondChen我不同意-这个问题的答案可能也间接地回答了我自己的问题,关于如何使用一系列参数调用new
。唉,这个问题是个骗局:Quantas 94 Heavy,Johathan Lonowski,阿尔尼塔克毫不费力地理解了我问题的含义,并给出了很好的答案。这个问题很简单,也很简洁,但更重要的是,已经有人这样问过了。如果你不喜欢这个问题,那么把它标记为一个傻瓜,而不是把它搁置。不是一个仇恨者,不是仇恨者,但这只是一个我知道即将到来的包装器(编辑时间==评论时间)。显然,我们需要一个更详细的答案。不过,我不是一个失败者,所以我不讨厌;)如果prototype
未定义,那么它将无法按照规范工作。@qantas94h是的,这就是我所说的“最低限度的必要性”。但是,要创建一个没有原型的函数非常困难,您必须调用对象。create(null)
,AFAICR.res?res:o
不符合标准,但概念很接近。@Alnitak,不,实际上,还有很多细微差别,例如,在函数a(){return 1};var b=新的A()
,b
将是一个对象,而不是值1
@zzzzBov啊,是的-因此它将是一个类型的
测试,然后:(无论如何,我说过这是最小可能的-我没有尝试使其100%符合ES规范+1,以链接到行为的文档。
Object.new = function (constructor /*, args */) {
function isObject(operand) {
// detect and refuse primitives
var type = typeof operand;
return type !== 'undefined' &&
type !== 'boolean' &&
type !== 'number' &&
type !== 'string' &&
operand !== null;
}
var argList = Array.prototype.slice.call(arguments, 1);
if (typeof constructor !== 'function') {
throw new TypeError((typeof constructor) + ' is not a function');
}
var proto = constructor.prototype;
var obj = Object.create(isObject(proto) ? proto : Object.prototype);
var result = constructor.apply(obj, argList);
return isObject(result) ? result : obj;
};
function Foo(one, two) {
this.one = one;
this.two = two;
}
var bar = Object.new(Foo, 'a', 'b');
console.log(bar instanceof Foo); // true
console.log(bar.one); // "a"
console.log(bar.two); // "b"
// 1. Let ref be the result of evaluating MemberExpression.
// 2. Let constructor be GetValue(ref).
Object.new = function (constructor /*, args */) {
function isObject(operand) {
// detect and refuse primitives
var type = typeof operand;
return type !== 'undefined' &&
type !== 'boolean' &&
type !== 'number' &&
type !== 'string' &&
operand !== null;
}
// 3. Let argList be the result of evaluating Arguments, producing an internal list of argument values (11.2.4).
var argList = Array.prototype.slice.call(arguments, 1);
// 4. If Type(constructor) is not Object, throw a TypeError exception.
// 5. If constructor does not implement the [[Construct]] internal method, throw a TypeError exception.
if (typeof constructor !== 'function') {
throw new TypeError((typeof constructor) + ' is not a function');
}
// 6. Return the result of calling the [[Construct]] internal method on constructor, providing the list argList as the argument values.
// For [[Construct]], it gets a bit out of order with current options for internal vs. abstractions.
// 5. Let proto be the value of calling the [[Get]] internal property of F with argument "prototype".
var proto = constructor.prototype;
// 1. Let obj be a newly created native ECMAScript object.
// 2. Set all the internal methods of obj as specified in 8.12.
// 3. Set the [[Class]] internal property of obj to "Object".
// 4. Set the [[Extensible]] internal property of obj to true.
//
// 6. If Type(proto) is Object, set the [[Prototype]] internal property of obj to proto.
// 7. If Type(proto) is not Object, set the [[Prototype]] internal property of obj to the standard built-in Object prototype object as described in 15.2.4.
var obj = Object.create(isObject(proto) ? proto : Object.prototype);
// 8. Let result be the result of calling the [[Call]] internal property of F, providing obj as the this value and providing the argument list passed into [[Construct]] as args.
var result = constructor.apply(obj, argList);
// 9. If Type(result) is Object then return result.
// 10. Return obj.
return isObject(result) ? result : obj;
};