【前端芝士树】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,一经查实,立即删除!

相关文章

C# 反射之Activator用法举例

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

MyBatis批量插入

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

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

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

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…

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

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

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

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

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…

Atcoder 084D - Small Multiple(最短路径+思维)

分析&#xff1a;这题脑洞新奇...居然是最短路...将0到k-1看做k个点&#xff0c;第t个点向(10*t0,1,2...,9)%k连一条长度为0,,1,2,..,9的边&#xff0c;然后枚举s1,2,...,9,算出所有从s到0的最短路&#xff0c;答案就是最短路s的最小值。 1 #include<iostream>2 #include…

Blazor学习之旅(5)数据绑定

【Blazor】| 总结/Edison Zhou大家好&#xff0c;我是Edison。最近在学习Blazor做全栈开发&#xff0c;因此根据老习惯&#xff0c;我会将我的学习过程记录下来&#xff0c;一来体系化整理&#xff0c;二来作为笔记供将来翻看。本篇&#xff0c;我们来了解下在Blazor中数据是如…

chrome开启touch屏幕点击事件

2019独角兽企业重金招聘Python工程师标准>>> 在chrome浏览器输入 chrome://flags/#top-chrome-md 找到属性 UI Layout for the browsers top chrome 选择Hybrid&#xff0c;重启chrome&#xff0c;如下图&#xff1a; 转载于:https://my.oschina.net/swingcoder/blo…

Linux服务器重启后crs_stat -t 命令无法正常使用以及解决思路

前提&#xff1a;在Linux系统中安装ASM&#xff0c;安装完ASM和Oracle数据库时都是正常使用的&#xff0c;但在重启服务器后Oracle相关命令不识别。1、[gridudevasm:/home/grid]$crsctl status res -t -bash: crsctl: command not found2、查看环境变量是否正常&#xff0c;命令…

python 打开某个exe_python定时检查启动某个exe程序(如果exe挂了)

详见代码如下&#xff1a;import threadingimport timeimport osimport subprocessdef get_process_count(imagename):p os.popen(tasklist /FI "IMAGENAME eq %s" % imagename)return p.read().count(imagename)def timer_start():t threading.Timer(120,watch_fu…

Google发布了Tensorflow Lite,用于移动电话的神经网络库

Google的工程副总Dave Burke宣布了一个专门针对移动电话而优化的Tensorflow新版本。\\这一新的软件库称为Tensorflow Lite&#xff0c;允许开发人员在用户的移动电话上实时地运行人工智能应用。据Burke介绍&#xff0c;该库在设计上力求更快和更小的同时&#xff0c;依然支持最…

4. ZooKeeper 基本操作

ZooKeeper的数据模型及其API支持以下九个基本操作&#xff1a; 操作描述create在ZooKeeper命名空间的指定路径中创建一个znodedelete从ZooKeeper命名空间的指定路径中删除一个znodeexists检查路径中是否存在znodegetChildren获取znode的子节点列表getData获取与znode相关的数据…

微软正式发布Azure Functions 2.0

微软正式发布Azure Functions的第二个版本&#xff0c;这是一个事件驱动的、按需计算的Azure平台服务。与版本1相比&#xff0c;新版本的Azure Functions包含的多项特性使开发人员可以更轻松地构建可伸缩的无服务器应用程序。2016年初&#xff0c;微软首次推出Azure Functions预…

CSS-下拉导航条

Web网站中很多时候都会出现下拉导航条&#xff0c;有的是通过CSS实现&#xff0c;有的通过JavaScript插件实现&#xff0c;其实CSS实现起来比较简单,先来看一个简版的下拉菜单: Html代码通过ul列表实现: 123456789101112131415161718<ul class"nav"> <li>…