-
2017-06-22 14:24:54
JS原型对象和原型链
在Javascript中,万物皆对象,但对象也有区别,大致可以分为两类,即:普通对象Object 和 函数对象Function。
一般而言,通过new Function产生的对象是函数对象,其他对象都是普通对象。
举例说明:
function f1(){ //todo } var f2 = function(){ //todo }; var f3 = new Function('x','console.log(x)'); var o1 = {}; var o2 = new Object(); var o3 = new f1(); console.log( typeof f1,//function typeof f2,//function typeof f3,//function typeof o1,//object typeof o2,//object typeof o3 //object ); >> function function function object object object
f1属于函数的声明,最常见的函数定义方式,f2实际上是一个匿名函数,把这个匿名函数赋值给了f2,属于函数表达式,f3不常见,但也是一种函数对象。
Function是JS自带的对象,f1,f2在创建的时候,JS会自动通过new Function()的方式来构建这些对象,因此,这三个对象都是通过new Function()创建的。
在Javascript中创建对象有两种方式:对象字面量和使用new表达式,o1和o2的创建恰好对应了这两种方式,重点讲一下o3, 如果用Java和C#的思路来理解的话,o3是f1的实例对象,o3和f1是同一类型,至少我以前这么认为,其实不然...
那么怎么理解呢? 很简单,看o3是不是通过new Function产生的, 显然不是,既然不是函数对象,那就是普通对象 。
通过对函数对象和普通对象的简单理解之后,我们再来了解一下Javascript中的原型和原型链:
在JS中,每当创建一个函数对象f1 时,该对象中都会内置一些属性,其中包括prototype和__proto__, prototype即原型对象,它记录着f1的一些属性和方法。
需要注意的是,prototype 对f1是不可见的,也就是说,f1不会查找prototype中的属性和方法。
function f(){} f.prototype.foo = "abc"; console.log(f.foo); //undefined
那么,prototype有什么用呢? 其实prototype的主要作用就是继承。 通俗一点讲,prototype中定义的属性和方法都是留给自己的“后代”用的,因此,子类完全可以访问prototype中的属性和方法。
想要知道f1是如何把prototype留给“后代”,我们需要了解一下JS中的原型链,此时,JS中的 __proto__ 入场了,这哥们长的很奇特,隐藏的也很深,以致于你经常见不到它,但它在普通对象和函数对象中都存在, 它的作用就是保存父类的prototype对象,JS在通过new 表达式创建一个对象的时候,通常会把父类的prototype赋值给新对象的__proto__属性,这样,就形成了一代代传承...
function f(){} f.prototype.foo = "abc"; var obj = new f(); console.log(obj.foo); //abc
现在我们知道,obj中__proto__保存的是f的prototype, 那么f的prototype中的__proto__中保存的是什么呢? 看下图:
如图所示,f.prototype的__proto__中保存的是Object.prototype,Object.prototype对象中也有__proto__,而从输出结果看,Object.prototype.__proto__ 是null,表示obj对象原型链的终结。如下图所示:
obj对象拥有这样一个原型链以后,当obj.foo执行时,obj会先查找自身是否有该属性,但不会查找自己的prototype,当找不到foo时,obj就沿着原型链依次去查找...
在上面的例子中,我们在f的prototype上定义了foo属性,这时obj就会在原型链上找到这个属性并执行。
最后,用几句话总结一下本文中涉及到的重点:
- 原型链的形成真正是靠__proto__ 而非prototype,当JS引擎执行对象的方法时,先查找对象本身是否存在该方法,如果不存在,会在原型链上查找,但不会查找自身的prototype。
- 一个对象的__proto__记录着自己的原型链,决定了自身的数据类型,改变__proto__就等于改变对象的数据类型。
- 函数的prototype不属于自身的原型链,它是子类创建的核心,决定了子类的数据类型,是连接子类原型链的桥梁。
- 在原型对象上定义方法和属性的目的是为了被子类继承和使用。
更多相关内容 -
js 原型对象和原型链理解
2020-12-02 12:51:28之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你... -
浅谈JS原型对象和原型链
2020-10-22 18:35:18主要为大家详细介绍了JS原型对象和原型链,感兴趣的小伙伴们可以参考一下 -
图文详解JavaScript的原型对象及原型链
2020-10-21 19:55:17许多人对JavaScript的原型及原型链仍感到困惑,网上的文章又大多长篇大论,令读者不明觉厉。下面小编将用最简洁明了的图文介绍JavaScript的原型及原型链。 -
JavaScript的原型对象和原型链
2020-08-26 18:44:08文章目录引子构造函数原型对象原型链继承 引子 有点意思的是,JavaScript的面向对象设计思想跟其他的面向对象语言(如Java、python)的设计思想有所不同。 JavaScript 虽是面向对象的语言,但JavaScript不使用类,不...引子
有点意思的是,JavaScript的面向对象设计思想跟其他的面向对象语言(如Java、python)的设计思想有所不同。
JavaScript 虽是面向对象的语言,但JavaScript不使用类,不创建类,也不会通过类来创建对象。所幸这样的局面在Es6出现之后得以改变(看来官方也觉得最初的JavaScript设计有点鸡肋)。而在Es6以前,我们不得不使用原型链来解决JavaScript中的有关面向对象的一系列问题:对象唯一性、抽象性、继承性、多态性。而原型链的最大的作用是解决对象的继承问题。
在JavaScript里,万物皆对象。构造函数(Function)是对象,构造函数的原型对象(Function.prototype)也是对象,对象都具有属性__proto__,__proto__指向构造该对象的构造函数的原型对象,而构造函数都会具有属性prototype,指向自身的原型对象。原型对象都具有属性constructor,其指向该原型对象所关联的构造函数,即构造函数.prototype.constructor==构造函数。要注意的是,__proto__是所有对象都具有的属性,而prototype是只有函数,或者说是构造函数才具有的属性,constructor是只有原型对象才具有的属性。
而什么为构造函数,什么为原型对象,下面我们来逐一唠唠,以便讲清Es6以前是怎样实现继承的。
构造函数
跟其他的面向对象语言不同,JavaScript不是采取new 一个class的方式来生成一个对象,而是new一个function来生成对象,被new的这个function被称为构造函数,而生成的对象被称为构造函数的实例对象。
要注意的是,当一个函数被用作构造函数,其中的this指针既不指向window,也不指向undefined,而是指向创建的实例对象。
如下列例子中,Person是atuo的构造函数,其中atuo是Person的一个实例对象
function Person(name){ this.name = name } var atuo = new Person("atuo")
原型对象
在构造函数中,有一个prototype属性,这个属性指向构造函数的原型对象,也就是说,所谓的原型对象就是prototype对象,而通过该构造函数生成的实例对象都会通过__proto__指向该构造函数的prototype对象。
由于所有的实例对象都会共享同一个构造函数的原型对象,所以一般在原型对象中放置固定不更改的属性值,让所有实例对象继承于它,这种属性又被称为引用属性,所以可以把原型对象理解为是实例对象的共享变量和方法;在构造函数中放置不同实例对象可以根据自己需要动态更改的属性值,这种属性被称为本地属性。当一个实例查找某个属性,在其本地属性查找不到的时候就会到引用属性去查找,即是到构造该实例的构造函数的原型对象去查找。有关这方面的内容,可以戳Javascript继承机制的设计思想。
function Person(name){ this.name = name } Person.prototype.age = 21 var atuo = new Person("atuo") console.log(atuo.age)
如上面atuo实例有本地属性name,引用属性age,在查找age时,在其构造函数的属性中查找不到(即是在本地属性中查找不到),就会上溯到其构造函数的原型对象Person.prototype中去查找。
构造函数、原型对象和实例对象之间的关系如图所示
原型链
综合上述所说的构造函数、原型对象、实例对象之间的关系。那么假如我们让一个构造函数的原型对象等于另一个构造函数的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个构造函数的原型对象的指针__proto__,相应地,如此层层递进,就构成了原型对象之间的链条。原型对象的链条就是顺着__proto__这条链层层递进的。这就是所谓的原型链的基本概念。
以下面代码为例,描绘一下其中的原型链。
function Student(name){ this.name = name } Student.prototype.hello = function(){ alert('Hello, ' + this.name + '!'); }; var xiaoming = new Student("xiaoming") var xiaohong = new Student("xiaohong")
如下图,黄色标注的线条就是其中的原型链。
继承
上面我们简述了原型链的相关概念,下面我们利用原型链把两个‘类’实现继承。假如我们有一个Parent和一个Child的构造函数,它们毫不相干。如图所示,它们的原型链是不相重合的
编写代码,使Child继承于Parent,使得两者原型链重合。
function extend(Child, Parent) { var F = function(){}; F.prototype = Parent.prototype; Child.prototype = new F(); Child.prototype.constructor = Child; Child.uber = Parent.prototype; }
-
JS原型对象和JS原型链
2022-01-06 15:08:141、类型与对象: 基本类型:string、number、boolean、object、null、undefined 引用类型:String、Number、Boolean、Object、Function、Array、Date、RegExp、Error 【对象】 2、创建引用类型对象,一般采用...1、类型与对象:
基本类型:string、number、boolean、object、null、undefined
引用类型:String、Number、Boolean、Object、Function、Array、Date、RegExp、Error
【对象】
2、创建引用类型对象,一般采用构造函数创建
如:
以上我们分别创建了三种不同类型的对象
在控制台打印,展开结果,看到有个内置属性[[Prototype]],有些浏览器是__proto__【两者是一样的意思,这个是对象的一个属性,在创建对象的时候就会生成】
Prototype,从字面意思上理解就是“原型的意思”,那这个属性有什么作用呢?
1、先看下图的分析:
以a为例:
对象a的原型是String,String的原型是Object
通过a.__proto__,可以获取到a的原型,即String
3、原型链
4、如何准确判断一个变量是数组类型
5、参考
b站--技术蛋老师视频
-
详解js中的原型,原型对象,原型链
2020-10-15 03:26:38主要介绍了js中的原型,原型对象,原型链的相关资料,文中讲解非常细致,代码帮助大家更好的理解和学习,感兴趣的朋友可以了解下 -
js原型对象和原型链理解
2019-03-01 20:22:35一. 函数对象 ...所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型) 所有函数拥有prototype属性(显示原型)(仅限函数) var a = {}; console.log(a.prototype); //undefined c...参考:https://blog.csdn.net/yucihent/article/details/79424506
文章内的图是参考一个大神的 但是找不到链接了一. 函数对象
- 所有引用类型(函数,数组,对象)都拥有__proto__属性(隐式原型)
- 所有函数拥有prototype属性(显示原型)(仅限函数)
var a = {}; console.log(a.prototype); //undefined console.log(a.__proto__); //Object{} var b = function(){}; console.log(b.prototype); //Object{} console.log(b.__proto__); //function(){} 由上述代码可知,prototype是函数才有的属性
- 原型对象:拥有prototype属性的对象,在定义函数时就被创建
- 原型对象的结构:
Function.prototype ={ constructor:Function, __proto__ : parent prototype, some prototype properties: };
二. __proto__属性指向
__proto__属性指向取决于对象创建时的实现方式
方式一:字面量方式
var a = {};
方式二:构造器方式
var A = function(){};
var a = new A();方式三:Object.create()方式
var a1 = {};
var a2 = Object.create(a1);> 大多数情况下,__proto__可以理解为“构造器的原型”,即__proto__ === constructor.prototype >(实例的隐式原型指向它构造函数的显示原型 这里的指向即恒等于)
这句话的理解可参考以下文章中的图
https://blog.csdn.net/qq_43553067/article/details/88075690三: 原型和原型链
-
什么是原型链?
由于__proto__是任何对象都有的属性,而js万物皆对象,所以会形成一条__proto__链接起来的链条,递归访问__proto__必须最终到头,并且值是null
当js引擎查找对象的属性时,先查找对象本身是否存在属性。如果不存在,会在原型链(其构造函数的prototype)上查找 -
示例
var A = function(){} var a = new A();
-
如图所示
- a.__proto__ ——> A.prototype(构造器function A 的原型对象) - a.__proto__.__proto__ ——> Object.prototype(构造器 function object的原型对象) - a.__proto__.__proto__.__proto__ ——> null
-
示例:
Function.prototype.a = "a"; Object.prototype.b = "b"; function Person(){} console.log(Person); //function Person() var p = new Person(); console.log(p); //Person {} 对象 console.log(p.a); //undefined console.log(p.b); //b
-
JavaScript使用原型和原型链实现对象继承的方法详解
2020-12-12 13:07:02本文实例讲述了JavaScript使用...以下就是原型链和原型的关系,引用网上的一张图 在Javascript中,每个函数都有一个原型属性prototype指向自身的原型,而由这个函数创建的对象也有一个proto属性指向这个原型,而函数的 -
深入浅析js原型链和vue构造函数
2020-12-10 15:35:40一、什么是原型链? 简单回顾下构造函数,原型和实例的关系: 每个构造函数(constructor)都有一个原型对象(prototype),原型对象都包含一个指向构造函数的指针,而实例(instance)都包含一个指向原型对象的内部指针. ... -
JavaScript原型对象与原型链
2022-03-22 09:23:20JavaScript原型对象与原型链 在JavaScript实际项目中,对象是十分重要的一个类型 无论是作为数据表现的一种形式或配置成工厂模式制造实例等等,这些用途在实际项目开发中都使用得非常广泛 依靠原型对象的特性可以... -
js-原型对象以及原型链
2022-02-28 21:10:07js-原型对象与原型链 -
js对象继承之原型链继承实例
2020-12-12 05:59:39本文实例讲述了js对象继承之原型链继承的用法。分享给大家供大家参考。具体分析如下: 代码如下:[removed] //定义猫的对象 var kitty = {color:’yellow’,bark:function(){alert(‘喵喵’);},climb:... -
学习javascript面向对象 理解javascript原型和原型链
2020-11-24 03:57:28【原型对象】这个对象包含可以由特定类型的所有实例共享的属性和方法。所有引用类型默认都继承了Object,而这个继承也是通过原型链实现的。所有函数的默认原型都是Object的实例,因此默认原型都会包含 -
javascript原型和原型链
2021-01-08 18:16:242、所有的引用类型(数组、对象、函数)都有一个__proto__属性(隐式原型属性),属性值是一个普通的对象 console.log(array.__proto__); console.log(object.__proto__) console.log(func.__proto__) 3、所有的函数... -
JavaScript作用域、闭包、对象与原型链概念及用法实例总结
2020-10-18 04:39:47主要介绍了JavaScript作用域、闭包、对象与原型链,结合实例形式总结分析了javascript中变量与函数的作用域、闭包、对象、原形链相关概念、用法及注意事项,需要的朋友可以参考下 -
JavaScript对象原型链原理解析
2020-11-21 23:06:07这篇文章主要介绍了JavaScript对象原型链原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 一个js对象,除了自己设置的属性外,还会自动生成proto、... -
一文秒懂JavaScript构造函数、实例、原型对象以及原型链
2020-10-14 20:56:03主要介绍了一文秒懂JavaScript构造函数、实例、原型对象以及原型链的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下 -
JavaScript原型对象和原型链
2017-11-01 16:42:46之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用很官方(其实自己不懂)的解释去描述。有一句话说的好:如果你不能把一个很复杂的东西用最简单的话语描述出来,那就说明你... -
JS原型和原型链原理与用法实例详解
2020-11-21 08:53:49本文实例讲述了JS原型和原型链原理与用法。分享给大家供大家参考,具体如下: Javascript语言的继承机制一直很难被人理解。 它没有”子类”和”父类”的概念,也没有”类”(class)和”实例”(instance)的区分,... -
js中的原型对象、对象原型和原型链
2021-06-12 09:10:351.什么是原型 prototype叫原型,是每一个构造函数身上的一个属性,这个属性是以对象的形式存在的 function People() { this.uname = 'zs'; } console.dir(People); -
一篇文章让你搞懂JavaScript 原型和原型链
2021-01-22 10:41:15原型和原型链作为深入学习JavaScript最重要的概念之一,如果掌握它了后,弄清楚例如:JavaScript的继承,new关键字的原来、封装及优化等概念将变得不在话下,那么下面我们开始关于原型和原型链的介绍。 什么是原型?...