js - __proto__ 、 prototype和constructor

零.资料与前言

0x1 材料:

  1.帮你彻底搞懂JS中的prototype、__proto__与constructor(图解)

0x2 前言

  之前也尝试总结过 js 中的 __proto__ 、 prototype 以及原型链相关的资料(JS 中的原型 -- prototype、__proto__ 以及原型链),不过彼时受限于经验等因素,没有多少条理,同时也存在诸多的的疑点。

  学习嘛,就是一个不断推翻自己的过程,本次总结如下:

 

一、总览

  以下例子贯穿全文...

function Foo(age) {
    this.age = age;   
}

let f1 = new Foo(16);

 

  先来张整体图解(原图较大,建议新标签页内观看):

 

  看着这花花绿绿的线条,头真的很大...不过没关系,分解过来看。

  注意: 图中的 '()' 仅代表这是一个函数对象,并非执行函数运算符。

 

二、__proto__

  __proto__ 在 ECMA 标准中是 [[Prototype]] ,各家浏览器的实现不一样,在 chrome 中就是 __proto__ ,稍微留意下即可。

  __proto__ 属性,当中存放(指向)着的是一个对象,粗略地讲就是以 “{ key: value }” 这种形式存在的对象(这里主要的为和 js 中的函数对象区分开来)。

  __proto__ 这个属性,理应是 “{k: v}” 对象所独有的,但是因为 js 中万物皆对象,所以 js 函数也是一种对象,所以函数也同样拥有这个属性,也正是因为这样,极容易产生困惑。

  我们从总图中把 __proto__ 单独抽出来:

  如上图所示,一个对象(f1)的 __proto__ 指向的另一个对象的,即指向它们的原型对象(也可以理解为父对象)。

  这个属性的作用是当访问一个对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,如果父对象也不存在这个属性,则继续往父对象的 __proto__ 属性所指向的那个对象(爷爷对象)里找,如果还没找到,则继续往上找…直到原型链顶端null(原始人。。。),再往上找就相当于在null上取值,会报错。

  通过这样一种链条式的值查找,就是我们常见的原型链,同时,这也是我们模拟继承的常用方法。

三、prototype 属性

  prototype 属性,函数独有,其存放(指向)的同样是一个对象

  从总图中将 prototype 抽出来:

 

  prototype 中存放的同样是一个对象,这个对象的含义是函数的原型对象,也就是以这个函数作为构造函数(其实所有函数都可以作为构造函数)所创建的实例原型对象,即 f1.__proto__ === Foo.prototype,这两个属性均指向同一个对象。

  prototype 的作用是包含可以由特定类型的所有实例共享的属性和方法,也就是让该函数所实例化的对象们都可以找到公用的属性和方法。任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。

 

四、 constructor 属性(函数)

  constructor 属性,和 __proto__ 一样,理应是对象独有,不过嘛,因为 js 所以 函数也有,但是不常用,故留意下即可。

  constructor 属性(变量),当中存放(指向)的是一个函数

  constructor 中存放的这个函数,就是该对象的构造函数,如对象 f1 以 Foo 为构造函数,那么  f1.constructor == Foo // true

  从上图中可以看到,所有的箭头都指向 Function 这个函数,并且 Function 的 constructor 是指向自己,故 constructor 属性的重点就是 Function 这个函数。如: Foo.constructor == Function // true

  从第 三 点我们知道,任何函数在创建的时候,其实会默认同时创建该函数的prototype对象。而在创建的这个 prototype 对象的时候,其中的 constructor 会显示指向这个函数,即上图中的  Foo.prototype.constructor == Foo 

 

五、总结

  1. __proto__ 和 constructor 是对象独有(伪)的;prototype 则是函数独有的;
  2. __proto__ 和 prototype 本身(存储的)是对象,constructor 本身(存储的)是函数;
  3. __proto__ 的常见作用是提供原型链, 以模拟继承特性;
  4. prototype 的常见作用是(自)定义其子代对象的公用属性和方法,并配合原型链提供给所有子代,即  f1.__proto__ == Foo.prototype ;
  5. constructor 的含义是存储(指向)该对象的构造函数;

 

  以上为本次总结的内容,如有缺陷,还望斧正。

 

转载于:https://www.cnblogs.com/cc-freiheit/p/11412433.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 JavaScript 中,每个对象都有一个 __proto__ 属性,指向其构造函数的原型对象。而每个函数都有一个 prototype 属性,指向该函数实例化出来的对象的原型对象。 __proto__ 属性是一个指针,指向该对象的构造函数的原型对象。通过 __proto__ 属性可以访问原型对象中的属性和方法。这个属性在 ES6 中已经被标准化,可以用 Object.getPrototypeOf() 来获取对象的原型。 prototype 属性是函数的一个特殊属性,指向一个对象。当函数用作构造函数创建实例对象时,该对象的原型会指向构造函数的 prototype 属性指向的对象。也就是说,该对象可以访问构造函数原型对象中的属性和方法。 举个例子: ``` function Person(name) { this.name = name; } Person.prototype.sayHello = function() { console.log(`Hello, my name is ${this.name}`); } const p = new Person('Tom'); console.log(p.__proto__ === Person.prototype); // true console.log(Person.prototype.constructor === Person); // true console.log(p.constructor === Person); // true ``` 在这个例子中,我们定义了一个构造函数 `Person`,并给其原型对象添加了一个 `sayHello` 方法。我们通过 `new` 关键字实例化了一个 `Person` 对象 `p`。这个对象的 `__proto__` 属性指向了 `Person.prototype`,因此我们可以通过 `p.__proto__.sayHello()` 或者 `Person.prototype.sayHello.call(p)` 来调用 `sayHello` 方法。同时,我们也可以通过 `Person.prototype` 来访问 `Person` 构造函数原型对象中的属性和方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值