我在哪里可以看到Node.js中JavaScript方法的源代码,如hasOwnProperty?

我一直在研究JavaScriptalgorithm和Big O面试。 我被告知知道内置方法的运行时间,比如Object.prototype.hasOwnPropertyArray.prototype.map ,是非常重要的。

什么是在node.js中查看这些函数的源代码的简单方法? 我有一个node.js的本地副本,我试图在我的文本编辑器中search这些方法,但并不像我想象的那么简单。

Object.prototype.hasOwnProperty()

从Javascript访问angular度来看,我认为你只需要完全理解obj.hasOwnProperty()在Javascript级别做什么,而不是如何在V8内部实现。

要做到这一点,你应该完全理解这个小片段:

 function MyConstructor() { this.methodB = function() {} } MyConstructor.prototype = { methodA: function() {} }; var o = new MyConstructor(); log(o.hasOwnProperty("methodA")); // false log(o.hasOwnProperty("methodB")); // true o.methodA = function() {}; // assign "own" property, overrides prototype log(o.hasOwnProperty("methodA")); // true 

这是因为.hasOwnProperty()只看对象本身而不看原型链。 因此,只有在原型链上或根本不存在的属性才会返回false ,直接在该对象上的属性将返回true


Array.prototype.map()

Array.prototype.map() Javascript中的Array.prototype.map() 在MDN上 ,它会告诉你它是如何工作的。 当然,如果你愿意的话,你也可以在Github仓库中做同样的searchtypes来查找.map()实现。

Array.prototype.map()真的很简单。 迭代一个数组,为数组中的每个元素调用一个函数。 该函数的每个返回值将用于构造一个新的数组,该数组将从调用返回到.map() 。 因此,在概念上,它被用来通过调用原始数组的每个元素上的某个变换函数将一个数组“映射”到另一个数组。

在最简单的化身中,你给数组的每个元素加1

 var origArray = [1,2,3]; var newArray = origArray.map(function(item, index, array) { return item + 1; }); console.log(newArray); // [2,3,4] 

实际的V8源代码:

如果你真的想看看它是如何在V8中实现的,这里是代码片段和链接到相关的实际代码文件。 正如你所看到的,大部分是用C ++来理解的,你必须了解对象是如何在内存中结构化的以及它们在V8中有什么C ++方法。 这是非常V8特定的,而不是一般的JavaScript知识。

我也包含了相关源文件的链接,所以如果你想看到这些文件中的其他上下文,你可以点击链接来看到。

在v8.h中 :

 V8_DEPRECATED("Use maybe version", bool HasOwnProperty(Local<String> key)); V8_WARN_UNUSED_RESULT Maybe<bool> HasOwnProperty(Local<Context> context, Local<Name> key); 

在api.cc中 :

 Maybe<bool> v8::Object::HasOwnProperty(Local<Context> context, Local<Name> key) { PREPARE_FOR_EXECUTION_PRIMITIVE(context, "v8::Object::HasOwnProperty()", bool); auto self = Utils::OpenHandle(this); auto key_val = Utils::OpenHandle(*key); auto result = i::JSReceiver::HasOwnProperty(self, key_val); has_pending_exception = result.IsNothing(); RETURN_ON_FAILED_EXECUTION_PRIMITIVE(bool); return result; } bool v8::Object::HasOwnProperty(Local<String> key) { auto context = ContextFromHeapObject(Utils::OpenHandle(this)); return HasOwnProperty(context, key).FromMaybe(false); } 

在v8natives.js中 :

 // ES6 7.3.11 function ObjectHasOwnProperty(value) { var name = TO_NAME(value); var object = TO_OBJECT(this); return %HasOwnProperty(object, name); } 

在对象中inl.h :

 Maybe<bool> JSReceiver::HasOwnProperty(Handle<JSReceiver> object, Handle<Name> name) { if (object->IsJSObject()) { // Shortcut LookupIterator it = LookupIterator::PropertyOrElement( object->GetIsolate(), object, name, LookupIterator::HIDDEN); return HasProperty(&it); } Maybe<PropertyAttributes> attributes = JSReceiver::GetOwnPropertyAttributes(object, name); MAYBE_RETURN(attributes, Nothing<bool>()); return Just(attributes.FromJust() != ABSENT); } 

在runtime-object.cc中 :

 static Object* HasOwnPropertyImplementation(Isolate* isolate, Handle<JSObject> object, Handle<Name> key) { Maybe<bool> maybe = JSReceiver::HasOwnProperty(object, key); if (!maybe.IsJust()) return isolate->heap()->exception(); if (maybe.FromJust()) return isolate->heap()->true_value(); // Handle hidden prototypes. If there's a hidden prototype above this thing // then we have to check it for properties, because they are supposed to // look like they are on this object. if (object->map()->has_hidden_prototype()) { PrototypeIterator iter(isolate, object); DCHECK(!iter.IsAtEnd()); // TODO(verwaest): The recursion is not necessary for keys that are array // indices. Removing this. // Casting to JSObject is fine because JSProxies are never used as // hidden prototypes. return HasOwnPropertyImplementation( isolate, PrototypeIterator::GetCurrent<JSObject>(iter), key); } RETURN_FAILURE_IF_SCHEDULED_EXCEPTION(isolate); return isolate->heap()->false_value(); } RUNTIME_FUNCTION(Runtime_HasOwnProperty) { HandleScope scope(isolate); DCHECK(args.length() == 2); CONVERT_ARG_HANDLE_CHECKED(Object, object, 0) CONVERT_ARG_HANDLE_CHECKED(Name, key, 1); uint32_t index; const bool key_is_array_index = key->AsArrayIndex(&index); // Only JS objects can have properties. if (object->IsJSObject()) { Handle<JSObject> js_obj = Handle<JSObject>::cast(object); // Fast case: either the key is a real named property or it is not // an array index and there are no interceptors or hidden // prototypes. // TODO(jkummerow): Make JSReceiver::HasOwnProperty fast enough to // handle all cases directly (without this custom fast path). Maybe<bool> maybe = Nothing<bool>(); if (key_is_array_index) { LookupIterator it(js_obj->GetIsolate(), js_obj, index, LookupIterator::HIDDEN); maybe = JSReceiver::HasProperty(&it); } else { maybe = JSObject::HasRealNamedProperty(js_obj, key); } if (!maybe.IsJust()) return isolate->heap()->exception(); DCHECK(!isolate->has_pending_exception()); if (maybe.FromJust()) { return isolate->heap()->true_value(); } Map* map = js_obj->map(); if (!key_is_array_index && !map->has_named_interceptor() && !map->has_hidden_prototype()) { return isolate->heap()->false_value(); } // Slow case. return HasOwnPropertyImplementation(isolate, Handle<JSObject>(js_obj), Handle<Name>(key)); } else if (object->IsString() && key_is_array_index) { // Well, there is one exception: Handle [] on strings. Handle<String> string = Handle<String>::cast(object); if (index < static_cast<uint32_t>(string->length())) { return isolate->heap()->true_value(); } } else if (object->IsJSProxy()) { Maybe<bool> result = JSReceiver::HasOwnProperty(Handle<JSProxy>::cast(object), key); if (!result.IsJust()) return isolate->heap()->exception(); return isolate->heap()->ToBoolean(result.FromJust()); } return isolate->heap()->false_value(); } 

这是node.js Github存储库 。 如果你知道要search什么,并且有足够的耐心去search所有的search结果,你通常可以find你需要的任何东西。 关于在Github上search的不幸的事情是我还没有find任何方法从search中删除所有的testing子目录,所以你最终在testing代码中的search命中率达到95%,而不是在实际的实现代码中。 但是,如果有足够的毅力,最终可以find你所需要的。