前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【前端芝士树】Javascript的原型与原型链

【前端芝士树】Javascript的原型与原型链

作者头像
CloudCat
发布2022-05-06 15:36:09
2130
发布2022-05-06 15:36:09
举报
文章被收录于专栏:一只想做全栈的猫

【前端芝士树】Javascript的原型、原型链以及继承机制

前端的面试中经常会遇到这个问题,自己也是一直似懂非懂,趁这个机会整理一下

0. 为什么会出现原型和原型链的概念

1994年,网景公司(Netscape)发布了Navigator浏览器0.9版,但是刚开始的Js没有继承机制,更别提像同时期兴盛的C++和Java这样拥有面向对象的概念。在实际的开发过程中,工程师们发现没有继承机制很难解决一些问题,必须有一种机制能将所有的对象关联起来。

Brendan Eich鉴于以上情况,但不想把Js设计得过为复杂,于是引入了new关键词constructor构造函数来简化对象的设计,引入了prototype函数对象来包含所有实例对象的构造函数的属性和方法,引入了proto原型链的概念解决继承的问题。

1. Javscript 函数和函数对象

代码语言:javascript
复制
var o1 = {}; 
var o2 =new Object();
var o3 = new f1();

function f1(){}; 
var f2 = function(){};
var f3 = new Function('str','console.log(str)');

凡是直接或者间接通过 new Function() 创建的对象都是函数对象,其他的都是普通对象。

在上面的程序中,o1、o2、o3都是普通对象,f1、f2、f3都是函数对象。

2. 构造函数

代码语言:javascript
复制
function Person(name, age, job) {
 this.name = name;
 this.age = age;
 this.job = job;
 this.sayName = function() { alert(this.name) } 
}
var person1 = new Person('Zaxlct', 28, 'Software Engineer');
var person2 = new Person('Mick', 23, 'Doctor');

person1person2 都是 构造函数 Person 的实例。 实例的构造函数属性(constructor)指向构造函数。

3. 原型对象

代码语言:javascript
复制
Person.prototype = {
   name:  'Zaxlct',
   age: 28,
   job: 'Software Engineer',
   sayName: function() {
     alert(this.name);
   }
}

每个函数对象都有一个 prototype 属性,这个属性就是函数的原型对象

每个对象都有 proto 属性,但只有函数对象才有 prototype 属性

clipboard.png
clipboard.png

在默认情况下,所有的原型对象都会自动获得一个 constructor(构造函数)属性,这个属性(是一个指针)指向 prototype 属性所在的函数(Person)

代码语言:javascript
复制
Person.prototype.constructor == Person

而在Person这个对象进行实例化的时候,实际上是创建了一个它的实例对象并赋值给它的 prototype,所以得出以下结论:

原型对象(Person.prototype)是 构造函数(Person)的一个实例。

4. _proto_

JS 在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做__proto__ 的内置属性,用于指向创建它的构造函数的原型对象,也就是prototype。

clipboard.png
clipboard.png
代码语言:javascript
复制
Person.prototype.constructor == Person;
person1.__proto__ == Person.prototype;
person1.constructor == Person;

看下面一段代码

代码语言:javascript
复制
Person.prototype.__proto__ === Object.prototype;

Person.prototype 是一个普通对象,我们无需关注它有哪些属性,只要记住它是一个普通对象。 因为一个 普通对象的构造函数 === Object 所以 Person.prototype.__proto__ === Object.prototype

5. 原型链

原型链的形成是真正是靠__proto__ 而非prototype。

代码语言:javascript
复制
person1.__proto__ === Person.prototype;
Person.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;
//Object.prototype.__proto__ === null,保证原型链能够正常结束。

Person.__proto__ === Function.prototype;
Object.__proto__ === Function.prototype;
Function.prototype.__proto__ === Object.prototype;

前面三项已经形成了一个原型链,那么后面代码中Person和Object的__proto__都是Function.prototype呢?

所有函数对象的proto都指向Function.prototype,它是一个空函数(Empty function)

代码语言:javascript
复制
Number.__proto__ === Function.prototype  // true
Number.constructor == Function //true

Boolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //true

String.__proto__ === Function.prototype  // true
String.constructor == Function //true

Object.__proto__ === Function.prototype  // true
Object.constructor == Function // true

Function.__proto__ === Function.prototype // true
Function.constructor == Function //true

Array.__proto__ === Function.prototype   // true
Array.constructor == Function //true

RegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //true

Error.__proto__ === Function.prototype   // true
Error.constructor == Function //true

Date.__proto__ === Function.prototype    // true
Date.constructor == Function //true

所有的构造器都来自于 Function.prototype,甚至包括根构造器Object及Function自身。所有构造器都继承了·Function.prototype·的属性及方法。如length、call、apply、bind

所以我们再举一个原型链的例子

代码语言:javascript
复制
let num = new Number();
num.__proto__ === Number.prototype;
Number.prototype.__proto__ === Function.prototype;
Funtion.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;

也可看下图的实现,更直观。

clipboard.png
clipboard.png

ok, 所以明白为什么Number、String、Array这样的对象实例能继承到Object的属性以及原型链是怎么一回事了吧。

参考文章 最详尽的 JS 原型与原型链终极详解,没有「可能是」。 三张图搞懂JavaScript的原型对象与原型链 - 水乙 - 博客园 Javascript继承机制的设计思想 - 阮一峰的网络日志

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 【前端芝士树】Javascript的原型、原型链以及继承机制
    • 0. 为什么会出现原型和原型链的概念
      • 1. Javscript 函数和函数对象
        • 2. 构造函数
          • 3. 原型对象
            • 4. _proto_
              • 5. 原型链
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档