2016-05-05 31 views
7

Röportajlar için JavaScript algoritmaları ve Big O çalışıyorum. Object.prototype.hasOwnProperty ve Array.prototype.map gibi yerleşik yöntemlerin çalışma zamanlarını bilmek önemli.Node.js'de hasOwnProperty gibi JavaScript yöntemleri için kaynak kodunu nereden görebilirim?

node.js'de bu işlevlerin kaynak kodunu görüntülemenin basit bir yolu nedir? Node.js'nin yerel bir kopyasına sahibim ve bu yöntemleri metin editörümde aramaya çalıştım, ancak düşündüğüm kadar basit değil.

+1

Eğer bir röportaj geçmesi edebilmek için size pratikte ihtiyaç ASLA olur yararsız çöp incelemek zorunda eğlenceli değil mi? – Hill

+0

Ayrıca bakınız [Dahili javascript fonksiyonları kaynağını görmek nasıl?] (Https://stackoverflow.com/q/22300206/1048572) – Bergi

cevap

10

Object.prototype.hasOwnProperty() görünümünde bir JavaScript görüşme açıdan

, ben sadece tamamen obj.hasOwnProperty() o V8 içinde uygulanacağı değil, nasıl JavaScript seviyesinde ne yaptığını anlamamız gerekir düşünürdüm.

Bunu yapmak için, tam bu küçük parçacığını anlamalıdır:

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() sadece nesnenin kendisinde değil, prototip zincirinde görünüyor olmasıdır. Bu nedenle, sadece prototip zincirinde bulunan veya hiç mevcut olmayan özellikler false'u döndürür ve doğrudan nesneye olan özellikler true değerini döndürür.


Array.prototype.map()

Array.prototype.map() için JavaScript Bir polyfill tam olarak nasıl çalıştığını gösterecektir here on MDN olduğunu. Tabii ki, isterseniz, Github deposunda yaptığım aynı arama türünü de .map() uygulamasını bulmak için yapabilirsiniz. Gerçekten çok basittir. Dizideki her öğe için bir işlev çağıran bir dizi üzerinde yineleyin. Bu işlevin her bir dönüş değeri, çağrıda .map()'a döndürülen yeni bir dizi oluşturmak için kullanılacaktır. Dolayısıyla, kavramsal olarak, orijinal dizinin her öğesinde bazı dönüştürme işlevlerini çağırarak bir diziyi diğerine "eşlemek" için kullanılır. En basit canlı örnek olarak

, bir dizinin her bir elemanına 1 ekleyin:

var origArray = [1,2,3]; 

var newArray = origArray.map(function(item, index, array) { 
    return item + 1; 
}); 

console.log(newArray); // [2,3,4] 

Gerçek V8 kaynak kodu: Gerçekten nasıl uygulandığı görmek istiyorsanız

V8'in içinde, burada kod parçacıkları ve ilgili gerçek kod dosyalarına bağlantılar vardır. Gördüğünüz gibi, çoğu C++'dadır ve bunu anlamak için, nesnelerin bellekte nasıl yapılandırıldığını ve V8'de dahili olarak sahip oldukları C++ yöntemlerini anlamalısınız. Bu çok genel bir Javascript bilgisi olmayan V8'e özgüdür.

İlgili kaynak dosyalara bağlantılar ekledim, bu nedenle bu dosyalarda başka bir bağlam görmek isterseniz, bağlantıyı tıklamak için bağlantılara tıklayabilirsiniz.

v8.h olarak:

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 olarak:

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 olarak:

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

objects-inl.h olarak:

yılında

:

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(); 
} 

Bu node.js Github repository olduğunu. Ne arayacağınızı biliyorsanız ve tüm arama isabetleri için yeterli sabrınız varsa, genellikle ihtiyacınız olan her şeyi bulabilirsiniz. Github'u arama konusundaki talihsiz şey, tüm test alt dizinlerini aramadan kaldırmanın bir yolunu bulamadım. Bu yüzden, gerçek uygulama kodunda değil, test kodundaki arama isabetleri% 95 ile bitiyor. Ancak, yeterli sebatla, neye ihtiyacınız olduğunu bulabilirsin.

+0

Faydalı araştırması. Linkler için teşekkürler. – TGrif

+0

V8'den gerçek kod parçacıkları yanıta eklendi. – jfriend00

+0

Bu, "doğru" yanıt olarak işaretlenmelidir. Yukarıda ve ötesinde ... –