Last active
August 29, 2015 14:03
-
-
Save jdfm/37030d0b6b28a5456cc5 to your computer and use it in GitHub Desktop.
Method to detect if some function is a native function or method.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var hasNativeCode = (function(hasNativeCodeRegexp){ // will this need changes because of ES6? | |
return function(f){ | |
return f && ( typeof f === 'function' && ( // This case checks functions/methods that are reported as functions | |
!f.hasOwnProperty('prototype') || // native methods don't have prototypes | |
hasNativeCodeRegexp.test(String(f)) // we don't care about the function name or arguments, just check if it's body is { [native code] } | |
)) || ( typeof f === 'object' && ( // certain browsers (that I know of, IE7 and IE8) report some native methods as object | |
!('constructor' in f) && // these methods don't have a constructor property and it can't be set | |
hasNativeCodeRegexp.test(String(f)) // it's string value will still be the native code string, so check for it | |
)); | |
}; | |
}(/^\s*function[^{]*{\s*\[native code\]\s*}\s*$/i)); | |
/* simple tests */ | |
var a = function(){ | |
// [native code] | |
} | |
var b = function(){ | |
// { [native code] } | |
} | |
var c = function(/* { [native code] } */){} | |
var d = new String('function{[native code]}') | |
var e = new Number(1); | |
e.valueOf = function(){return 'function{[native code]}';}; | |
var f = {}; | |
f.toString = function(){return 'function{[native code]}';}; | |
console.assert(hasNativeCode(a) === false, 'a does not have native code') | |
console.assert(hasNativeCode(b) === false, 'b does not have native code') | |
console.assert(hasNativeCode(c) === false, 'c does not have native code') | |
console.assert(hasNativeCode(d) === false, 'd does not have native code') | |
console.assert(hasNativeCode(e) === false, 'e does not have native code') | |
console.assert(hasNativeCode(+e) === false, 'e\'s value does not have native code') | |
console.assert(hasNativeCode(f) === false, 'f does not have native code') | |
console.assert(hasNativeCode(a.constructor) === true, 'Function has native code') | |
console.assert(hasNativeCode(a.constructor.prototype) === true, 'Function.prototype has native code') | |
console.assert(hasNativeCode(document.body.getAttribute) === true, 'document.body.getAttribute has native code') | |
console.log('Everything is in working order.'); |
It seems that certain browsers report methods as object when using typeof. I corrected the code to reflect this new (rather old) information.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Notes:
Native methods like
Function.prototype.bind
orArray.prototype.slice
don't have prototypes themselves, whereas native functions do, such as Function and Object and whatnot. This is true for the Function.prototype method as well (yes, you read that right, Function.prototype is also a method, it's basically a noop).If you delete the prototype of a function, or set it to
null
orundefined
it will still return true when checking for it via hasOwnProperty, so, as far as I know, you can't fake not having a prototype.Constructors may, or may not be, depending on your browser, callables (they could be objects), but trying to actually call them will result in a "TypeError: Illegal Constructor" message. It's not that they're not callable, they are, it's just that if you expect to be able to use these functions as is, you're going to have a bad time.
The only valid use that I see for this function is to check if some function or method has native code.