我在哪里可以看到Node.js中JavaScript方法的源代码,例如hasOwnProperty? [英] Where can I see the source code for JavaScript methods, such as hasOwnProperty, in Node.js?

查看:117
本文介绍了我在哪里可以看到Node.js中JavaScript方法的源代码,例如hasOwnProperty?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在研究JavaScript算法和Big O进行访谈。我被告知知道内置方法的运行时,例如 Object.prototype.hasOwnProperty Array.prototype.map ,很重要。

I have been studying JavaScript algorithms and Big O for interviews. I was told that knowing the runtimes of built-in methods, such as Object.prototype.hasOwnProperty and Array.prototype.map, is important.

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

What is a simple way to view the source code for these functions in node.js? I have a local copy of node.js, and I tried to search for these methods in my text editor, but it's not as straightforward as I thought.

推荐答案

Object.prototype.hasOwnProperty()

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

From a Javascript interview point of view, I would think you just need to fully understand what obj.hasOwnProperty() does at the Javascript level, not how it's implemented inside of V8.

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

To do that, you should fully understand this little snippet:

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

This is because .hasOwnProperty() looks only on the object itself and not on the prototype chain. So properties which are only on the prototype chain or do not exist at all will return false and properties which are directly on the object will return true.

Array.prototype.map()

Javascript中用于 Array.prototype.map()的polyfill是这里是MDN ,它将向您展示它的确切工作原理。当然,您可以在Github存储库中执行与上面相同类型的搜索,以便在需要时查找 .map()实现。

A polyfill in Javascript for Array.prototype.map() is here on MDN which will show you exactly how it works. You can, of course, do the same type of search I did above in the Github repository to find the .map() implementation too if you want.

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

Array.prototype.map() is pretty simple really. Iterate over an array, calling a function for each item in the array. Each return value of that function will be used to construct a new array that will be returned from the call to .map(). So, conceptually, it's used to "map" one array to another by calling some transform function on each element of the original array.

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

In the simplest incarnation, you add 1 to each element of an array:

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知识。

If you really want to see how it is implemented inside of V8, here are code snippets and links to the relevant actual code files. As you can see, most of it is in C++ and to understand it, you have to understand how objects are structured in memory and what C++ methods they have internally in V8. This is very V8-specific, not general Javascript knowledge.

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

I've included links to the relevant source files too so if you want to see other context in those files, you can click on the links to see that.

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

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

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存储库。如果您知道要搜索什么并且有足够的耐心来浏览所有搜索命中,您通常可以找到所需的任何内容。关于在Github上搜索的不幸之处是我没有找到任何方法从搜索中删除所有测试子目录,因此您最终会在测试代码中找到95%的搜索命中,而不是实际的实现代码。但是,有足够的持久性,你最终可以找到你需要的东西。

This is the node.js Github repository. If you know what to search for and have enough patience to wade through all the search hits, you can generally find anything you need. The unfortunate thing about searching on Github is I have not found any way to remove all the test sub-directories from the search so you end up with 95% of the search hits in the test code, not in the actual implementation code. But, with enough persistence, you can eventually find what you need.

这篇关于我在哪里可以看到Node.js中JavaScript方法的源代码,例如hasOwnProperty?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆