Object.prototype.hasOwnProperty()
Aus Javascript Interview Sicht würde ich glaube, Sie brauchen nur zu verstehen, was obj.hasOwnProperty()
auf der Ebene Javascript tut, nicht, wie es im Inneren des V8 realisiert wird.
, das zu tun, sollten Sie diesen kleinen Schnipsel verstehen:
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
Dies liegt daran, .hasOwnProperty()
nur auf dem Objekt schaut selbst und nicht auf der Prototypkette. Eigenschaften, die nur in der Prototypkette vorhanden sind oder überhaupt nicht vorhanden sind, geben false
zurück und Eigenschaften, die sich direkt auf dem Objekt befinden, geben true
zurück.
Array.prototype.map()
A polyfill in Javascript für Array.prototype.map()
ist here on MDN, die Ihnen genau zeigen, wie es funktioniert. Sie können natürlich die gleiche Art von Suche durchführen, die ich oben im Github-Repository durchgeführt habe, um die .map()
Implementierung zu finden, wenn Sie möchten.
Array.prototype.map()
ist wirklich ziemlich einfach. Iterate über ein Array und ruft eine Funktion für jedes Element im Array auf. Jeder Rückgabewert dieser Funktion wird verwendet, um ein neues Array zu konstruieren, das von dem Aufruf an .map()
zurückgegeben wird. Es wird also konzeptionell verwendet, um ein Array einem anderen zuzuordnen, indem eine Transformationsfunktion für jedes Element des ursprünglichen Arrays aufgerufen wird.
Im einfachsten Inkarnation, fügen Sie 1
jedem Element eines Arrays:
var origArray = [1,2,3];
var newArray = origArray.map(function(item, index, array) {
return item + 1;
});
console.log(newArray); // [2,3,4]
Actual Code V8 Quelle:
Wenn Sie wirklich wollen, um zu sehen, wie es umgesetzt Innerhalb von V8, hier sind Code-Schnipsel und Links zu den relevanten tatsächlichen Code-Dateien. Wie Sie sehen können, ist das meiste davon in C++ und um es zu verstehen, müssen Sie verstehen, wie Objekte im Speicher strukturiert sind und welche C++ - Methoden sie intern in V8 haben. Dies ist sehr V8-spezifisch, nicht allgemeines Javascript-Wissen.
Ich habe auch Links zu den relevanten Quelldateien eingefügt. Wenn Sie also einen anderen Kontext in diesen Dateien sehen möchten, können Sie auf die Links klicken, um das zu sehen.
In 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);
In 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);
}
In v8natives.js:
// ES6 7.3.11
function ObjectHasOwnProperty(value) {
var name = TO_NAME(value);
var object = TO_OBJECT(this);
return %HasOwnProperty(object, name);
}
In objects-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);
}
In 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();
}
Dies ist node.js Github repository. Wenn Sie wissen, wonach Sie suchen müssen und genügend Geduld haben, um alle Suchtreffer zu durchsuchen, können Sie im Allgemeinen alles finden, was Sie brauchen. Das Problem bei der Suche auf Github ist, dass ich keine Möglichkeit gefunden habe, alle Unterverzeichnisse des Tests aus der Suche zu entfernen, sodass Sie 95% der Suchtreffer im Testcode und nicht im eigentlichen Implementierungscode finden. Aber mit genug Ausdauer können Sie schließlich finden, was Sie brauchen.
Ist es nicht lustig, dass Sie unnützen Müll studieren müssen, den Sie in der Praxis NIEMALS brauchen würden, um ein Interview zu bestehen? – Hill
Siehe auch [So sehen Sie die Quelle der integrierten JavaScript-Funktionen?] (Https://Stackoverflow.com/q/22300206/1048572) – Bergi