我正在尝试确定javascript中的函数是简单的,简单的(匿名)函数,还是构造函数(具有原型的函数)。到目前为止,我已经提出了以下功能:
function isPlainFunction(value) {
var own = Object.getOwnPropertyNames(value.prototype),
ctorIndex = own.indexOf('constructor');
if ( ctorIndex !== -1 ) {
own.splice( ctorIndex, 1);
}
if (own.length) {
return false;
}
// walk prototype chain
var proto = Object.getPrototypeOf(value.prototype);
if (proto === Object.prototype) {
return true;
}
return isPlainFunction(proto);
}
我只针对ES5,(node.js),但我不确定这是否涵盖了所有边缘情况,或者是否还有一些我没有找到关于此主题的内容。
我(大致)考虑了以下测试用例:
assert.ok( isPlainFunction(function(){}) );
var bar = function(){};
bar.prototype = { get one(){ return 1 } };
assert.equal( isPlainFunction(bar), false );
var foo = function(){};
foo.prototype = Object.create( bar );
assert.equal( isPlainFunction(bar), false );
也就是说,任何具有原型的函数或从非本机类型之一继承原型......
答案 0 :(得分:2)
如果您要测试的是一个函数是否应该用作构造函数,那么很遗憾,这无法准确确定。
您可以在任何函数上调用new
运算符,无论是否以这种方式使用都没有问题。
如果我有这种方法,例如:
function doSomethingWithThisObject(someValue) {
this.someVariable = someValue;
}
具有以下原型:
doSomethingWithThisObject.prototype = { prototypeVariable : 'I came from prototype' };
我可以通过以下方式使用它:
// Use my function as a constructor:
var obj = new doSomethingWithThisObject('hi there!');
console.log(obj.someVariable); // prints "hi there!"
console.log(obj.prototypeVariable); // prints "I came from prototype"
// Use my function in an object:
var myObject = {
doSomething : doSomethingWithThisObject
};
myObject.doSomething('hi again!');
console.log(myObject.someVariable); // prints "hi again!"
console.log(myObject.prototypeVariable); // prints "undefined"
// Use my function to change global state:
doSomethingWithThisObject('you owe me ice cream!');
console.log(someVariable); // prints "you owe me ice cream!"
console.log(prototypeVariable); // prints "undefined"
除非在代码中的某处指定了意图,否则无法确定其中一个用例是否正确。
有些人建议使用大写的第一个字母命名构造函数方法,以确定它们应该用作构造函数。如果您根据项目的编码指南决定这个建议,您可以简单地检查函数的名称是否以大写字母开头,这将表示编写该函数的人打算将其用作构造函数。
答案 1 :(得分:0)
正如Ben Barkay所说,任何函数都可以通过 new 关键字成为JS中的构造函数。在幕后所有 new 正在设置函数的上下文 - 你可以通过一个简单的测试看到这个:
function test() {
console.log(this)
}
test()
output: Window {top: Window, window: Window…}
new test()
output: test {}
test {}
在JS中你需要创建一个构造函数的函数是一个 new 关键字,所有 new 都设置函数的 this 变量。所以任何函数都可以成为构造函数。
区分anon函数更容易:如果它没有名称,则它是匿名的:
//anon:
(function() {
console.log("I'm anon")
})()
var anon = function() {
console.log("I, too, am anon")
}
如果您以编程方式需要函数的名称,则可以通过function.name
获取它答案 2 :(得分:0)
确定某个功能是否没有扩展prototype
,例如可以假设它比普通函数更多,以下函数将返回false
:
function isPlainFunction(value) {
if (typeof value !== 'function') {
return false;
}
var own = Object.getOwnPropertyNames(value.prototype);
if ( own.length >= 2 || ( own.indexOf('constructor') < 0 && own.length >= 1 ) ) {
return false;
}
return Object.getPrototypeOf(value.prototype) === Object.prototype;
}