关键词:
研究javascript的原型概念两天,看到这篇文章后,终于恍然大悟,里面的图展示了一切!大部分内容转载自:https://segmentfault.com/a/1190000005824449
一切皆为对象
殊不知,JavaScript的世界中的对象,追根溯源来自于一个 null
「一切皆为对象」,这句着实是一手好营销,易记,易上口,印象深刻。
万物初生时,一个null
对象,凭空而生,接着Object
、Function
学着null
的模样塑造了自己,并且它们彼此之间喜结连理,提供了prototype
和constructor
,一个给子孙提供了基因,一个则制造万千子子孙孙。
在JavaScript中,null
也是作为一个对象存在,基于它继承的子子孙孙,当属对象。乍一看,null
像是上帝,而Object
和Function
犹如JavaScript世界中的亚当与夏娃。
原型指针 __proto__
在JavaScript中,每个对象都拥有一个原型对象,而指向该原型对象的内部指针则是__proto__
,通过它可以从中继承原型对象的属性,原型是JavaScript中的基因链接,有了这个,才能知道这个对象的祖祖辈辈。从对象中的__proto__
可以访问到他所继承的原型对象。
var a = new Array();
a.__proto__ === Array.prototype // true
上面代码中,创建了一个Array的实例a
,该实例的原型指向了Array.prototype
。Array.prototype
本身也是一个对象,也有继承的原型:
a.__proto__.__proto__ === Object.prototype // true
// 等同于 Array.prototype.__proto__ === Object.prototype
这就说了明了,Array本身也是继承自Object的,那么Object的原型指向的是谁呢?
a.__proto__.__proto__.__proto__ === null // true
// 等同于 Object.prototype.__proto__ === null
所以说,JavaScript中的对象,追根溯源都是来自一个null对象。佛曰:万物皆空,善哉善哉。
除了使用.__proto__
方式访问对象的原型,还可以通过Object.getPrototypeOf
方法来获取对象的原型,以及通过Object.setPrototypeOf
方法来重写对象的原型。
值得注意的是,按照语言标准,__proto__
属性只有浏览器才需要部署,其他环境可以没有这个属性,而且前后的两根下划线,表示它本质是一个内部属性,不应该对使用者暴露。因此,应该尽量少用这个属性,而是用 Object.getPrototypeof
和Object.setPrototypeOf
,进行原型对象的读写操作。这里用__proto__
属性来描述对象中的原型,是因为这样来得更加形象,且容易理解。
原型对象 prototype
函数作为JavaScript中的一等公民,它既是函数又是对象,函数的原型指向的是Function.prototype
var Foo = function() {}
Foo.__proto__ === Function.prototype // true
函数实例除了拥有__proto__
属性之外,还拥有prototype
属性。通过该函数构造的新的实例对象,其原型指针__proto__
会指向该函数的prototype
属性。
var a = new Foo();
a.__proto__ === Foo.prototype; // true
而函数的prototype
属性,本身是一个由Object
构造的实例对象。
Foo.prototype.__proto__ === Object.prototype; // true
prototype
属性很特殊,它还有一个隐式的constructor
,指向了构造函数本身。
Foo.prototype.constructor === Foo; // true
a.constructor === Foo; // true
a.constructor === Foo.prototype.constructor; // true
原型链
概念:
原型链作为实现继承的主要方法,其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。
每个构造函数都有一个原型对象(prototype
),原型对象都包含一个指向构造函数的指针(constructor
),而实例都包含一个指向原型对象的内部指针(__proto__
)。
那么,假如我们让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构造了实例与原型的链条,这就是原型链的基本概念。
意义:“原型链”的作用在于,当读取对象的某个属性时,JavaScript引擎先寻找对象本身的属性,如果找不到,就到它的原型去找,如果还是找不到,就到原型的原型去找。以此类推,如果直到最顶层的Object.prototype还是找不到,则返回undefine。
亲子鉴定
在JavaScript中,也存在鉴定亲子之间DNA关系的方法:
-
instanceof 运算符返回一个布尔值,表示一个对象是否由某个构造函数创建。
-
Object.isPrototypeOf() 只要某个对象处在原型链上,isProtypeOf都返回true
var Bar = function() {}
var b = new Bar();
b instanceof Bar // true
Bar.prototype.isPrototypeOf(b) // true
Object.prototype.isPrototypeOf(Bar) // true
要注意,实例b
的原型是Bar.prototype
而不是Bar
一张历史悠久的图
这是一张描述了Object
、Function
以及一个函数实例Foo
他们之间原型之间联系。如果理解了上面的概念,这张图是不难读懂。
从上图中,能看到一个有趣的地方。
-
Function.prototype.__proto__
指向了Object.prototype
,这说明Function.prototype
是一个Object
实例,那么应当是先有的Object
再有Function
。 -
但是
Object.prototype.constructor.__proto__
又指向了Function.prototype
。这样看来,没有Function
,Object
也不能创建实例。
这就产生了一种类「先有鸡还是先有蛋」的经典问题,到底是先有的Object
还是先有的Function
呢?
这么哲学向的问题,留给你思考了。
总结一句话:
对象:
自身属性
构造器属性(constructor)
原型(__proto__)
函数(构造方法):
自身属性
构造器属性(constructor)
原型属性(prototype)
原型(__proto__)
对象.原型(__proto__) === 函数(构造方法).原型属性(prototype)
对象.构造器属性 === 函数(构造方法)
javascript概念总结:作用域闭包对象与原型链
1 JavaScript变量作用域1.1函数作用域没有块作用域:即作用域不是以{}包围的,其作用域完成由函数来决定,因而if/for等语句中的花括号不是独立的作用域。如前述,JS的在函数中定义的局部变量只对这个函数内部可见,称之谓... 查看详情
javascript----原型,原型链(什么是原型)
...把这部分抽取出来讲。再讲这个概念时我们先大致了解下JavaScript中的“对象”。什么是对象?JavaScript权威指南中给的解释是:对象是一种复合数据类型,它们将多个数据值集中在一个单元中,而且允许使用名字来存取这些值。或... 查看详情
javascript--面向对象原型继承(代码片段)
1.面向对象原型继承面向对象编程JavaScript的面向对象编程和大多数其他语言如Java、C#的面向对象编程都不太一样。如果你熟悉Java或C#,很好,你一定明白面向对象的两个基本概念:所以,类和实例是大多数面向对... 查看详情
javascript-面向对象
...づ ̄3 ̄)づ╭?~ 面向对象的基本概念:类和实例。JavaScript不区分类和实例,通过原型来实现面向对象。1.类--->原型对象JavaScript是一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。这种... 查看详情
08.21javascript07object概念创建对象创建属性操作方法遍历原型
#Object###Object的概念* 对象可以看做是属性的无序集合###创建对象Object* 直接量{}* 构造函数newObject() ###对象属性的操作* 运算符 .* 运算符[]* 属性检测 in console 查看详情
javascript中的原型详解(代码片段)
前言 都知道,原型能够使对象的方法达到复用的目的,而不是每个对象都存在相同方法。概念 在详细了解原型之前,需要明白以下概念: prototype:原型,函数自带的属性,也是一个对象; constructor... 查看详情
总结javascript基础概念系列计划分为三个部分:作用域,事件循环,原型链。
主要问题: 1、javaScript代码的编译和执行过程,词法作用域规则?2、this的动态绑定方式有几种?3、全局和函数之外是不是还有其他的作用域?4、为什么代码规范多禁止with、eval? 一、js编译执行(一)、(预)编译期JS... 查看详情
javascript原型和原型链
前言在了解原型和原型链之前,我们先了解一部分概念,constructor,prototype,proto。constructor在之前判断数据类型的文章:javaScript常见数据类型检查校验有提到过关于构造函数的属性constructorconstructor的是返回创建实例对象的 查看详情
javascript原型
javascript里面没有类的概念,对象由对象实例化。使用原型初始化对象:functionPerson(){Person.prototype.name=‘sophie‘;Person.prototype.showName=function(){console.log(this.name);}; varperson=newPerson();person.showName();}使用对象字 查看详情
原型链
原型链概念原型链是一种机制,指的是JavaScript每个对象包括原型对象都有一个内置的[[proto]]属性指向创建它的函数对象的原型对象,即prototype属性。作用原型链的存在,主要是为了实现对象的继承。理解要理解原型链,需要从... 查看详情
对javascript的原型,原型链和继承的个人理解
继承是OO语言中一个最为人津津乐道的概念,也是初接触Javascript的初学者难理解的概念=。=继承主要分为两种:一种是接口继承,另一种是实现继承。而在ECMAScript中只支持实现继承,所以我们今天来讨论讨论实现继承。实现继承... 查看详情
javascript中高级进阶推荐一个javascript进阶深入系列专题系列(涉及原型作用域执行上下文变量对象this闭包按值传递callapplybindnew继承等
推荐一个JavaScript进阶深入系列、专题系列,其中涉及原型、作用域、执行上下文、变量对象、this、闭包、按值传递、call、apply、bind、new、继承等JS语言中的比较难懂的概念。作者写的很深入用心,详细,想要深入搞... 查看详情
javascript扩展原型链浅析
...简单的概念介绍和解析,本文将浅析一些原型链的扩展。javaScript原型和原型链http://lewyon.xyz/prototype.html扩展原型链使用new操作符利用原型是对象的特性,实例化对象的时候,继承多个构造函数的属性和方法兼容性:支持目前 查看详情
浅谈javascript的原型及原型链
浅谈javascript的原型及原型链 这里,我们列出原型的几个概念,如下:prototype属性[[prototype]]__proto__prototype属性只要创建了一个函数,就会为该函数创建一个prototype属性,指向该函数的原型对象。实例对象是不会拥有该属... 查看详情
javascript的原型与继承
首先,什么是原型:JavaScript里所有函数,变量方法都是对象,而对象对应的就是原型(prototype).所以以此来看,JS里任何的对象都有一个原型对象,而默认的原型对象就处在原型链的最顶端。现在说到了一个新的概念,什么是原型... 查看详情
JavaScript:公共方法和原型
】JavaScript:公共方法和原型【英文标题】:JavaScript:Publicmethodsandprototypes【发布时间】:2011-03-1200:41:26【问题描述】:我不完全确定如何在JS中实现OOP概念。我有一个完全在其构造函数中声明的类:functionAjaxList(settings)//allthesevarsa... 查看详情
第一百零九节,javascript面向对象与原型
JavaScript面向对象与原型 学习要点:1.学习条件2.创建对象3.原型4.继承 ECMAScript有两种开发模式:1.函数式(过程化),2.面向对象(OOP)。面向对象的语言有一个标志,那就是类的概念,而通过类可以创建任意多个具有相同属性... 查看详情
《javascript闯关记》之原型及原型链
原型链是一种机制,指的是JavaScript每个对象都有一个内置的__proto__属性指向创建它的构造函数的prototype(原型)属性。原型链的作用是为了实现对象的继承,要理解原型链,需要先从函数对象、constructor、new、prototype、__proto__这... 查看详情