JavaScript对象之进阶一步一步捋清prototype

7次阅读

共计 1755 个字符,预计需要花费 5 分钟才能阅读完成。

一步一步捋清 prototype

前言

  • 刚刚开始学习 JavaScript 就知道,这是一门“面向对象的语言”,但各种原理和 c ++,java 等典型的面向对象语言明显不同,“原型链”,es6 中的“class”,都彰显着 js 中面向对象的与众不同。
  • 究竟什么是原型 prototype 呢?如何在 JavaScript 中实现“类”呢?

一张图

图片分析

这是我总结的一张图片,简单的描绘了原型和构造函数、实例间的复杂关系。

  1. 全局对象 window 属性 Object(此处仅用来举例,其余属性暂且不提),指向 Object()这个 函数对象
  2. Object 中存着 prototype,它指向了原型(原型中包含了对象的所有方法和属性)
  3. 当我们声明一个实例 let obj = new Object(), 你可以发现它天生就带着__proto__属性。而__prototype 竟然和Object.prototype 指向了同一个对象。我们知道,它就是 原型

一些思考

1.Object.prototype(即对象类的原型)的原型是什么呢?

  • 我们不妨打印出来试一试:
    应该和你想的一样,对象类的原型就是原型链的尽头了,它只是一个普通的对象,并没有原型。

2.Object.prototype中的 constructor 是什么?有什么用?

  • 你应该还记得我们刚刚像这样 let obj = new Object(); 创建了一个对象实例 obj,那么再来看看这个,你应该就一目了然了

    没错,constructor 存在的意义就是为了让实例化地对象找到它的构造函数。(对实例化的数组,constructor 指向 Array;对实例化地函数,constructor 指向 Function)

3. 但你不能人为 constructor 指向的一定是构造出当前对象的函数。

  • 例如,你能说出 Object.prototype.constructor 指向谁吗?
    你看,这个结果是不是很让人头大??Object.prototype指向了原型,而原型的 constructor 的又指回了 Object。实际上这种试验是无意义的,因为我们要知道,constructor 是提供给 实例,用来定位它的构造函数的属性,而不是给原型本身使用的。
  • 而这种 Object.prototype.constructor ===Object 的现象,其实源于人为设计。为了让实例的对象都继承原型中的 constructor,无法避免出现这种现象。

4. 我们尝试更深入一些?尝试剖析一下数组对象的相关结构。

  • 问题 1:Array.prototype.__proto__===?

    • 直接来看结果吧
    • 为什么会有这种结果呢?其实我们只需要理解清 Array.prototype 的本质就好了,其实 Array.prototype 只是一个 Object()构造出的对象实例而已,一个对象实例的原型当然是 Object.prototype 啊!换句话说 Array.prototype 和 obj 在本质上是一样的!
  • 问题 2:let arr=[1,2,3]; 属于对象的方法 hasOwnProperty 是如何在数组实例上生效的呢?

    1. arr 在自身寻找 hasOwnProperty 方法,发现没有。
    2. arr 又到他爸爸 arr.__proto__即 Array.prototype 中寻找 hasOwnProperty 方法,仍然找不到 =
    3. arr 再到他爷爷 arr.__proto__.__proto__即 Object.prototype 中寻找,找到了这个方法,于是 arr 调用了这个方法。

prototype vs class

代码对比

// prototype 方法
function Person(name, age) {
        this.name = name,
        this.age = age
}
Person.prototype.sayHi = function() {console.log('你好,我叫'+this.name);
}

//class 方法
class Person{constructor(name,age){
        this.name = name;
        this.age = age;
    }
    sayHi() {console.log('你好,我叫'+this.name);
    }
}

体会

  • class 只是 prototype 方法的语法糖而已,本质上没有区别
  • 理解 prototype => 熟练使用 prototype => 无压力使用 class
正文完
 0