javaScript原型与原型链

Posted 酒 客

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了javaScript原型与原型链相关的知识,希望对你有一定的参考价值。

javascript中的原型链

认识对象的原型–隐式原型

​ JavaScript当中每个对象都有一个特殊的内置属性 [[prototype]](这个就是__proto__隐式原型),这个特殊的对象可以指向另外一个对象。

那么这个对象有什么用呢?

  • 当我们通过引用对象的属性key来获取一个value时,它会触发 [[Get]]的操作;
  • 这个操作会首先检查该对象是否有对应的属性,如果有的话就使用它;
  • 如果对象中没有该属性,那么会访问对象[[prototype]]内置属性指向的对象上的属性;

那么如果通过字面量直接创建一个对象,这个对象也会有这样的属性吗?如果有,应该如何获取这个属性呢?

​ 答案是有的,只要是对象都会有这样的一个内置属性;

获取的方式有两种:

  • 方式一:通过对象的 proto 属性可以获取到(但是这个是早期浏览器自己添加的,存在一定的兼容性题);
  • 方式二:通过 Object.getPrototypeOf 方法可以获取到;

函数的原型 prototype–显式原型

那么我们知道上面的东西对于我们的构造函数创建对象来说有什么用呢?它的意义是非常重大的,接下来我们继续来探讨; 这里我们又要引入一个新的概念:所有的函数都有一个prototype的属性

你可能会有问题,是不是因为函数是一个对象,所以它有prototype的属性呢?不是的,因为它是一个函数,才有了这个特殊的属性;而不是它是一个对象,所以有这个特殊的属性;

再看new操作符

我们前面讲过new关键字的步骤如下:

  • 1.在内存中创建一个新的对象(空对象);
  • 2.这个对象内部的[[prototype]]属性会被赋值为该构造函数的prototype属性;(后面详细讲);

那么也就意味着我们通过Person构造函数创建出来的所有对象的[[prototype]]属性都指向Person.prototype:

创建对象的内存表现

赋值为新的对象

constructor属性

​ 事实上原型对象上面是有一个属性的:constructor默认情况下原型上都会添加一个属性叫做constructor,这个constructor指向当前的构造函数对象

创建对象 – 构造函数和原型组合

function Person(name, age, height, address) 
  this.name = name
  this.age = age
  this.height = height
  this.address = address


Person.prototype.eating = function() 
  console.log(this.name + "在吃东西~")


Person.prototype.running = function() 
  console.log(this.name + "在跑步~")


var p1 = new Person("why", 18, 1.88, "北京市")
var p2 = new Person("kobe", 20, 1.98, "洛杉矶市")

p1.eating()
p2.eating()

JavaScript中的类和对象

当我们编写如下代码的时候,我们会如何来称呼这个Person呢?

在JS中Person应该被称之为是一个构造函数;

从很多面向对象语言过来的开发者,也习惯称之为类,因为类可以帮助我们创建出来对象p1、p2;

如果从面向对象的编程范式角度来看,Person确实是可以称之为类的;

function Person()
    

const p=new Person()

面向对象的特性 – 继承

面向对象有三大特性:封装、继承、多态

  • 封装:我们前面将属性和方法封装到一个类中,可以称之为封装的过程;
  • 继承:继承是面向对象中非常重要的,不仅仅可以减少重复代码的数量,也是多态前提(纯面向对象中);
  • 多态:不同的对象在执行时表现出不同的形态;

那么这里我们核心讲继承。

​ 那么继承是做什么呢?继承可以帮助我们将重复的代码和逻辑抽取到父类中,子类只需要直接继承过来使用即可。那么JavaScript当中如何实现继承呢?不着急,我们先来看一下JavaScript原型链的机制;再利用原型链的机制实现一下继承;

JavaScript原型链

​ 在真正实现继承之前,我们先来理解一个非常重要的概念:原型链。我们知道,从一个对象上获取属性,如果在当前对象中没有获取到就会去它的原型上面获取:

Object的原型

那么什么地方是原型链的尽头呢?比如第三个对象是否也是有原型__proto__属性呢?

我们会发现它打印的是 [Object: null prototype]

  • 事实上这个原型就是我们最顶层的原型了
  • 从Object直接创建出来的对象的原型都是 [Object: null prototype] 。

那么我们可能会问题: [Object: null prototype] 原型有什么特殊吗?

  • 特殊一:该对象有原型属性,但是它的原型属性已经指向的是null,也就是已经是顶层原型了;
  • 特殊二:该对象上有很多默认的属性和方法;

原型链关系的内存图

Object是所有类的父类

从我们上面的Object原型我们可以得出一个结论:原型链最顶层的原型对象就是Object的原型对象

原型继承关系

以上是关于javaScript原型与原型链的主要内容,如果未能解决你的问题,请参考以下文章

原型与原型链(javascript)

JavaScript 原型与原型链

JavaScript理解原型与原型链

JavaScript中的原型与原型链

javaScript原型与原型链

javascript 原型与原型链(笔记)