Skip to content

Instantly share code, notes, and snippets.

@jdfm
Last active August 29, 2015 14:03
Show Gist options
  • Save jdfm/37030d0b6b28a5456cc5 to your computer and use it in GitHub Desktop.
Save jdfm/37030d0b6b28a5456cc5 to your computer and use it in GitHub Desktop.
Method to detect if some function is a native function or method.
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.');
@jdfm
Copy link
Author

jdfm commented Jul 7, 2014

Notes:

Native methods like Function.prototype.bind or Array.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 or undefined 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.

@jdfm
Copy link
Author

jdfm commented Sep 20, 2014

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