Js 代码在执行时,会被 V8 引擎解析,这时 V8 会用不同的模板来处理 Js 中的对象和函数。例如:

  • ObjectTemplate 用来创建对象
  • FunctionTemplate 用来创建函数
  • PrototypeTemplate 用来创建函数原型

V8 中的定义得到以下结论:

  • Js 中的函数都是 FunctionTemplate 创建出来的,返回值的是 FunctionTemplate 实例
  • Js 中的对象都是 ObjectTemplate 创建出来的,返回值的是 ObjectTemplate 实例
  • Js 中函数的原型(prototype)都是通过 PrototypeTemplate 创建出来的,返回值是 ObjectTemplate 实例

所以 Js 中的对象的原型可以这样判断:

  • 所有的对象的原型都是 Object.prototype,自定义构造函数的实例除外。
  • 自定义构造函数的实例,它的原型是对应的构造函数原型。

在 Js 中的函数原型判断就更加简单了。

  • 所有的函数原型,都是 Function.prototype。

下图展示了所有的内置构造函数,他们的原型都是 Function.prototype。
image.png
看到这里,你是否也可以一看就看出任何对象的原型呢?

附:V8 中的函数解析案例

了解完原型链之后,我们看一下 V8 中的函数解析。

  1. function Student(name) {
  2. this.name = name;
  3. }
  4. Student.prototype.study = function () {
  5. console.log("study js");
  6. };
  7. const student = new Student('xiaoming')

这段代码在 V8 中会这样执行:

  1. // 创建一个函数
  2. v8::Local<v8::FunctionTemplate> Student = v8::FunctionTemplate::New();
  3. // 获取函数原型
  4. v8::Local<v8::Template> proto_Student = Student->PrototypeTemplate();
  5. // 设置原型上的方法
  6. proto_Student->Set("study", v8::FunctionTemplate::New(InvokeCallback));
  7. // 获取函数实例
  8. v8::Local<v8::ObjectTemplate> instance_Student = Student->InstanceTemplate();
  9. // 设置实例的属性
  10. instance_Student->Set("name", String::New('xiaoming'));
  11. // 返回构造函数
  12. v8::Local<v8::Function> function = Student->GetFunction();
  13. // 返回构造函数实例
  14. v8::Local<v8::Object> instance = function->NewInstance();

以上代码可以分为 4 个步骤:

  • 创建函数模板。
  • 在函数模板中,拿到函数原型,并赋值。
  • 在函数模板中,拿到函数实例,并赋值。
  • 返回构造函数。
  • 返回构造函数实例。