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

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

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

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

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

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

1. Javscript 函数和函数对象

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. 构造函数

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. 原型对象

Person.prototype = {name:  'Zaxlct',age: 28,job: 'Software Engineer',sayName: function() {alert(this.name);}
}

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

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

clipboard.png

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

Person.prototype.constructor == Person

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

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

4. _proto_

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

clipboard.png

Person.prototype.constructor == Person;
person1.__proto__ == Person.prototype;
person1.constructor == Person;

看下面一段代码

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

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

5. 原型链

原型链的形成是真正是靠__proto__ 而非prototype。
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)
Number.__proto__ === Function.prototype  // true
Number.constructor == Function //trueBoolean.__proto__ === Function.prototype // true
Boolean.constructor == Function //trueString.__proto__ === Function.prototype  // true
String.constructor == Function //trueObject.__proto__ === Function.prototype  // true
Object.constructor == Function // trueFunction.__proto__ === Function.prototype // true
Function.constructor == Function //trueArray.__proto__ === Function.prototype   // true
Array.constructor == Function //trueRegExp.__proto__ === Function.prototype  // true
RegExp.constructor == Function //trueError.__proto__ === Function.prototype   // true
Error.constructor == Function //trueDate.__proto__ === Function.prototype    // true
Date.constructor == Function //true
所有的构造器都来自于 Function.prototype,甚至包括根构造器Object及Function自身。所有构造器都继承了·Function.prototype·的属性及方法。如length、call、apply、bind

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

let num = new Number();
num.__proto__ === Number.prototype;
Number.prototype.__proto__ === Function.prototype;
Funtion.prototype.__proto__ === Object.prototype;
Object.prototype.__proto__ === null;

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

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/281917.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

神奇的幻方2015提高组d1t1

题目描述 幻方是一种很神奇的N*N矩阵:它由数字1,2,3,……,N*N构成,且每行、每列及两条对角线上的数字之和都相同。 当N为奇数时,我们可以通过以下方法构建一个幻方: 首先将1写在第一行的中间。 之后,按如下方式从小到大…

goldengate mysql_使用GoldenGate实现MySQL到Oracle的数据实时同步

step 1: 配置mysql修改配置文件my.ini#for goldengatelog-bin "C:/mysql/logbin/logbin.log"binlog-format ROWlog-bin-index "C:\mysql\logindex"binlog_cache_size32mmax_binlog_cache_size512mmax_binlog_size512m添加数据库用户ggs,具有…

C# 反射之Activator用法举例

概述程序运行时,通过反射可以得到其它程序集或者自己程序集代码的各种信息,包括类、函数、变量等来实例化它们,执行它们,操作它们,实际上就是获取程序在内存中的映像,然后基于这个映像进行各种操作。Activa…

MyBatis批量插入

转载于:https://blog.51cto.com/12701034/1929672

狐狸文│区块链发展的正路

(图片出自网络,版权归原作者所有)最近看了一本书:《美国增长的起落》。这本书是大部头,但看起来很过瘾。通过对这本书的阅读,我更新了自己对区块链发展的理解。这一年,“区块链”很热&#xff0…

mysql 一主一备_Mysql一个主一备

Mysql主从复制 -- 一主一备主从复制原理:Mysql的主从复制是mysql本身自带的一个功能,不需要额外的第三方软件可以实现,其复制功能并不是copy文件实现的,而是借助binlog日志文件里面的SQL命令实现的主从复制,可以理解为…

解决安装Weblogic domain卡住问题(Primeton BPS)

这两天一直有一个问题困扰我,在suse10weblogic(920,923,100,103)上安装bpm产品失败。有些版本是创建domain的时候卡在create security information上,有些版本卡在安装包start weblogic上。但是在winXPweblogic10.3bpm安装成功。 经过几番GOOGLE,终于找到…

cocos2d-js 热更新具体解释(一)

本文将会具体解说cocos2d-js下的热更新机制。这篇内容先给大家介绍一下两个manifest文件就当热身了。首先介绍project.manifest: 举个样例 {"packageUrl" : "http://192.168.1.108/games/dragon_gold","remoteManifestUrl" : "…

Qt之水平/垂直布局(QBoxLayout、QHBoxLayout、QVBoxLayout)

简述 QBoxLayout可以在水平方向或垂直方向上排列控件,由QHBoxLayout、QVBoxLayout所继承。 QHBoxLayout:水平布局,在水平方向上排列控件,即:左右排列。 QVBoxLayout:垂直布局,在垂直方向上排列控…

Optaplanner终于支持多线程并行运行 - Multithreaded incremental solving

Optaplanner 7.9.0.Final之前,启动引擎开始对一个Problem进行规划的时候,只能是单线程进行的。也就是说,当引擎对每一个possible solution进行分数计算的过程中,细化到每个步骤(Caculation),都只能排队在同一个线程中依…

python棋盘格_干货必看 | Python的turtle库之经典棋盘格

国际棋盘格是一个由9横9纵的线组成的格子正方形,用Python的turtle库进行绘制的时候,先做9横9纵的线,再填上灰色小正方形,这就可以完成一个棋盘格了,下面是具体的操作步骤。(一)整体代码1、import turtleimport turtle2…

一位技术老人给.NET初学者的一些建议

.NET平台应用领域众多,随着这些年的不断更新迭代,日趋臻善,也受到越来越多的开发者青睐。自从2000 年6 月22 日 微软推出Microsoft.NET 战略 ,至今已有22载,这些年新技术,新框架层出不穷,目不暇…

android 本地数据库sqlite的封装

单机android sqlite数据库的实现,这个数据库可与程序一起生成在安装包中一、下载sqlite3.exe文件二、运行 cmd 转到sqlite3.exe 所在目录 运行 sqlite3.exe 数据库名.db然后会出现sqlite>的命令提示符输入创建表的语句, create table 表名&#xf…

ResourceManager中的Resource Estimator框架介绍与算法剖析

欢迎大家前往腾讯云社区,获取更多腾讯海量技术实践干货哦~ 本文由宋超发表于云社区专栏 本文首先介绍了Hadoop中的ResourceManager中的estimator service的框架与运行流程,然后对其中用到的资源估算算法进行了原理剖析。 一. Resource Estimator Service…

几十款 WPF 控件 - UI 库,总有一款适合你

几十款 WPF 控件 - UI 库,总有一款适合你独立观察员 2022 年 10 月 16 日引言众所周知,使用 WPF 框架能够开发出功能强大、界面美观的桌面端应用。能够达到这个效果,各种 WPF 的控件库、UI 库功不可没。所以,想着能不能收集一下目…

mysql将系统权限授予用户_mysql创建用户并授予权限

1、create schema [数据库名称] default character set utf8 collate utf8_general_ci;--创建数据库采用create schema和create database创建数据库的效果一样。2、create user ‘[用户名称]‘‘%‘ identified by ‘[用户密码]‘;--创建用户密码8位以上,包括&#…

Android Studio导出jar包

Eclipse直接有个Export,可以直接导出jar包。AS相对Eclipse变化很大,编译脚本变成了Gradle,各种导包操作都有差异。 下面是AS导出jar的过程: 第一步,修改app下的build.grade。 apply plugin: com.android.application修改为 apply …

GitHub Actions构建镜像并部署服务

目的通过GitHub的Actions来(白嫖)部署.Net服务到阿里云服务器。环境准备需要一个阿里云服务器并且该服务器还安装了docker环境,如果环境安装不清楚可以查看之前的文章。创建镜像仓库在阿里云的容器镜像服务中,创建一个镜像仓库用来存储我们测试的镜像&am…

20165232 缓冲区溢出漏洞实验

缓冲区溢出漏洞实验 实验准备 实验环境需要32位的Linux系统,需要下载安装一些用于编译 32 位 C 程序的软件包,代码如下: $ sudo apt-get update$ sudo apt-get install -y lib32z1 libc6-dev-i386$ sudo apt-get install -y lib32readline-gp…

使用qt的qtcore库怎么包含_GitHub - coologic/QtCoreExamples: QtCore模块相关类库范例

QtCoreExamplesQtCore模块相关类库范例QJsonExampleQt进行Json文件读写范例QXmlExampleQt使用QXmlStreamReader/QXmlStreamWriter类进行XML文件读写范例非不是使用QtXML模块QSharedMemoryExampleQt使用QSharedMemory实现共享内存QSettingsExample(Blog)Qt使用QSettings配置读写…