百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

一篇文章读懂JS原型和原型链(js原型和原型链有什么特点)

myzbx 2025-06-18 23:01 3 浏览

前言

你好! 欢迎阅读本篇文章,今天我将要用一篇文章带你深入理解JavaScript中的原型和原型链,让我们一起揭开原型神秘的面试,一起窥探其中的奥妙。

一切皆是对象

看到这个标题你可能就有你可能就有疑问了,怎么这篇文章一开始就要胡扯了,然后准备要关闭这篇这篇文章。别急、客官,接下来就让我们仔细掰扯掰扯这句话

“一切皆是对象”是没错,关键在于你如何理解这个“对象”这个概念。这句话的重点也在于此。

在理解对象之前,我们先引用一个我们的老朋友 typeof ,相信很多前端的同学都应该知道这个JavaScript的常用运算符,如果你不知道,请仔细阅读下面文字。

我们都知道 typeof 可以判断一个变量的类型,返回值共有一下几种( undefined、number、string、boolean、function、object、Symbol )其中 Symbol 是 ES6 引入的新类型。

function test() {
    var x;
    console.log(typeof x)             //undefined
    console.log(typeof 100)           //number
    console.log(typeof 'typeof')      //string
    console.log(typeof true)          //boolean


    console.log(typeof [1,2,3,4])       //object
    console.log(typeof {a:1,b:2})       //object
    console.log(typeof null)            //object null在这里为空对象(注意)
    console.log(typeof new Number(100)) //object

    console.log(typeof function(){})    //function
}

上面代码列出的是 typeof 返回的几种值,其中代码前四种是值类型,余下的几种情况都是引用类型,他们也都是对象。关于引用类型和值类型的区别请看我们另一篇文章值类型和引用类型.

对象是若干属性的集合,对象里面的一切都是属性,都是以键值对的形式出现,其中方法也是一种特殊的属性。属性的值也能是一个对象(禁止套娃qAq)对象可以用instanceof判断,记住一切(应用类型)都是对象,对象是属性的集合,一切对象都是通过函数来创建的

原型知多少

说到原型我们就不得不说 prototype 我们知道每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。我放了两张图片帮你理解(qwq)

上图SuperType是函数,他的原型就是SuperType Prototype,原型的constructor属性指向它的构造函数SuperType

上图是对象的Object的以及它的原型,我们可以看到原型上有很多我们常用的属性和方法,应为一切对象的原型都直接或间接的指向了它,因此可以使用上面的方法。

上面说到每一个函数都有自己的prototype,也就是原型,那么通过 new 生成的函数实例呢?这里就不禁要疑问了,其实每个new出来的实例,以及每一个对象都有一个__proto__,即隐式原型。

上面图片显示了对象obj的__proto__属性,下面我再放一张Object的prototype

从上面的截图看出,obj.proto__和Object.prototype是一样的
我们用一张图表示。

从图中我们得知每个对象都有都有一个__proto,并且指向该对象函数的prototype。

唯一的特例Object.prototype的__proto__指向的是null

还有就是,函数也是对象,函数也有一个__proto__,指向Function.prototype,函数是由Function创建出来的,而Function又被自身创建。

var foo = new Function("x","y","return x+y")

就是这样,建议不要这样创建函数

原型链和继承

下面用一张详细的图,请仔细阅读,我们根据这张图讲解原型链

要说起原型链,我们不得不用到一个工具instanceof,对于引用类型,我们想要知道引用类型的具体是数组还是对象,就要用到这个工具。如下所示

function Foo(){}
var f1 = new Foo()
console.log(foo instanceof Foo)      //true
console.log(foo instanceof Object)   //true


结合上图我们我们来看看,instanceof运算符的规则就是,实例foo沿着__proto__这条线,同时Foo沿着prototype这条线来找,如果这两条线找到了同一个对象,那么就返回true,否则就返回false, instanceof表示一种继承关系,或者原型链的结构

JavaScript是通过原型链的方式来实现继承的,又被称作为原型链对象继承,对于一个对象,它可以访问它原型对象的属性。同理,原型对象也是一个属性,它也有自己的原型,因此也可以继承它原型对象原型的属性。

访问一个对象的属性时,现在基本的对象内找,如果找不到,就沿着__proto__这条链向上找。

几种常见的继承方式

组合继承

组合继承(combination inheritance),有时候也叫做伪经典继承,指的是将原型链和借用构造函数的

技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方

法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数

复用,又能够保证每个实例都有它自己的属性。下面来看一个例子

function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
};
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function(){
alert(this.age);
};
var instance1 = new SubType("Nicholas", 29);
instance1.colors.push("black");
alert(instance1.colors); //"red,blue,green,black"
instance1.sayName(); //"Nicholas";
instance1.sayAge(); //29
var instance2 = new SubType("Greg", 27);
alert(instance2.colors); //"red,blue,green"
instance2.sayName(); //"Greg";
instance2.sayAge(); //27

ES6中继承

ES6是通过class实现了类,通过extends实现了标准化继承,然而,class、extends本质上还是语法糖,通过bable可以将其转译为ES5代码执行。

ES6中的class、extends使用的是ES5中寄生组合继承,并对寄生组合继承作出了一下优化,如下所示

ES6中继承使用Object.create()以SuperClass的原型对象创建了一个新的原型对象,即SubClass.prototype.proto = SuperClass.prototype。 同时使其constructor属性指向SubClass。

ES5的继承是子类的原型对象__proto__属性指向父类的原型对象,而ES6中继承是子类__proto__指向父类。

写在最后

以上就是本人对原型和原型链的整理和记录,因为资料来源比较多,在整理和书写是难免出现错误,如果你看到这里,发现原文有错误的地方,或者有什么想要分享的,也欢迎在评论区留言,一起学习,加油,奥利给


相关推荐

怎么恢复7z文件 7z文件删除了怎么恢复

7z是一种压缩格式的文件,它运用LZMA压缩算法,该压缩算法的输出稍后被算数编码进行处理以便后续进一步压缩,压缩比十分高。我们可以将文件压缩成这种格式,便于传输,保存,占空间少。了解更多7z文件知识...

郎酒让消费者喝得明明白白 算术题里有答案

日前,『郎酒酱香产品企业内控准则』颁布,郎酒首次公开酱香产品生产全过程,公布酱香产品产能、储能及投放计划。随后,郎酒官微向消费者发出「品控算术题」有奖问答。郎酒亮出家底,消费者踊跃留言。8天后,谜底揭...

学龄前,比识字、算术更重要的是这三件事

“为了给孩子选择一家合适的幼儿园,我曾穿梭于纽约各家幼儿园的开放日,这些幼儿员既包括主流的公立幼儿园,还包括那些遥不可及的私人幼儿园。我的目的就是想了解他们的教育理念是什么,到底厉害在哪里,看看对于我...

参加CSP-J信奥赛需要掌握数学知识

在C++语法的学习中需要储备的数学知识如下①数据类型:需要知道整数、正整数、负整数、小数、判断对错②算术运算符:加法、减法、乘法、除法、取模运算③关系表达式:大于、大于等于、小于、小...

1g米饭能做多少深蹲?今天我们来算一算

减重我们都知道3分在练,7分在吃,吃这件事情上,真的是每一口都算数。今天我们来算一笔账,1粒米饭可以做多少事情?本着认真负责的态度,今天在食物秤上称了1g米饭,是16粒。根据能量换算:100g米饭是4...

web 自动化测试,一定得掌握的 8 个核心知识点

使用cypress进行端对端测试,和其他的一些框架有一个显著不同的地方,它使用JavaScript作为编程语言。传统主流的selenium框架是支持多语言的,大多数QA会的pytho...

大话C语言:赋值运算符(c语言中赋值运算符是什么)

赋值运算符是最基本的运算符之一,用于将右侧的值或表达式的计算结果赋给左侧的变量。它是一个二元运算符,意味着它需要两个操作数:一个是目标变量(左侧),另一个是要赋给该变量的值或表达式(右侧)。赋值运算符...

Vue进阶(幺幺伍):js 将字符串转换为boolean

Boolean();参数为0、null和无参数返回false,有参数返回true。Boolean("");//输出为:falseBoolean(null);//输出为...

mongodb查询的语法(大于,小于,大于或等于,小于或等于等等)

1).大于,小于,大于或等于,小于或等于$gt:大于$lt:小于$gte:大于或等于$lte:小于或等于例子:db.collection.find({"field":{$gt:valu...

Python学不会来打我(21)python表达式知识点汇总

在Python中,表达式是由变量、运算符、函数调用等组合而成的语句,用于产生值或执行特定操作。以下是对Python中常见表达式的详细讲解:1.1算术表达式涉及数学运算的表达式。例如:a=5b...

C|数据存储地址与字节偏移、数据索引

话说C是面向内存的编程语言。数据要能存得进去,取得出来,且要考虑效率。不管是顺序存储还是链式存储,其寻址方式总是很重要。顺序存储是连续存储。同质结构的数组通过其索引表示位置偏移,异质结构的结构体通过其...

下班后累懵?4 个 JS 手写题帮你搞定前端面试高频考点

打工人下班后最痛苦的事,莫过于拖着疲惫的身子还要啃前端面试题吧?看着那些密密麻麻的JS代码,脑子都快转不动了!别担心,今天咱就用轻松的方式,带你吃透4道高频手写题,让你在面试时自信满满,再也不...

嵌入式数据库sqlite3【进阶篇】-子句和函数的使用,小白一文入门

sqlite在《嵌入式数据库sqlite3命令操作基础篇-增删改查,小白一文入门》一文中讲解了如何实现sqlite3的基本操作增删改查,本文介绍一些其他复杂一点的操作。比如where、orderby...

前缀表达式与后缀表达式(前缀表达式后缀表达式中缀表达式计算)

昨天晚上和儿子一起学习了前缀表达式和后缀表达式。这应该是字符串算式如何被计算机识别并计算的2种方法。本来是想先给他讲一个逆波兰式(后缀表达式),以后再讲前缀表达式。没想到他还挺聪明,很快就把2个都掌握...

Python快速入门教程1:基本语法、数据类型、运算符、数字字符串

Python3的基础教程,涵盖了基本语法、数据类型、类型转换、解释器、注释、运算符、数字和字符串等内容,并附有使用实例场景。Python3的基础教程,涵盖了基本语法、数据类型、类型转换、解释器、注释、...