js原型链原理看图说明

合集下载

简单粗暴地理解js原型链

简单粗暴地理解js原型链

简单粗暴地理解js原型链原型链理解起来有点绕了,网上资料也是很多,每次晚上睡不着的时候总喜欢在网上找点原型链和闭包的文章看,效果极好。

不要纠结于那一堆术语了,那除了让你脑筋拧成麻花,真的不能帮你什么。

简单粗暴点看原型链吧,想点与代码无关的事,比如人、妖以及人妖。

1)人是人他妈生的,妖是妖他妈生的。

人和妖都是对象实例,而人他妈和妖他妈就是原型。

原型也是对象,叫原型对象。

2)人他妈和人他爸啪啪啪能生出一堆人宝宝、妖他妈和妖他爸啪啪啪能生出一堆妖宝宝,啪啪啪就是构造函数,俗称造人。

3)人他妈会记录啪啪啪的信息,所以可以通过人他妈找到啪啪啪的信息,也就是说能通过原型对象找到构造函数。

4)人他妈可以生很多宝宝,但这些宝宝只有一个妈妈,这就是原型的唯一性。

5)人他妈也是由人他妈他妈生的,通过人他妈找到人他妈他妈,再通过人他妈他妈找到人他妈他妈……,这个关系叫做原型链。

6)原型链并不是无限的,当你通过人他妈一直往上找,最后发现你会发现人他妈他妈他妈……的他妈都不是人,也就是原型链最终指向null。

7)人他妈生的人会有人的样子,妖他妈生的妖会有妖的丑陋,这叫继承。

8)你继承了你妈的肤色,你妈继承了你妈他妈的肤色,你妈他妈……,这就是原型链的继承。

9)你没有家,那你家指的就是你妈家;你妈也没有家,那你家指的就是你妈他妈家……这就是原型链的向上搜索。

10)你会继承你妈的样子,但是你也可以去染发洗剪吹,就是说对象的属性可以自定义,会覆盖继承得到的属性。

11)虽然你洗剪吹了染成黄毛了,但你不能改变你妈的样子,你妈生的弟弟妹妹跟你的黄毛洗剪吹没一点关系,就是说对象实例不能改动原型的属性。

12)但是你家被你玩火烧了的话,那就是说你家你妈家你弟们家都被烧了,这就是原型属性的共享。

13)你妈外号阿珍,邻居大娘都叫你阿珍儿,但你妈头发从飘柔做成了金毛狮王后,隔壁大婶都改口叫你金毛狮王子,这叫原型的动态性。

14)你妈爱美,又跑到韩国整形,整到你妈他妈都认不出来,即使你妈头发换回飘柔了,但隔壁邻居还是叫你金毛狮王子。

JavaScript中原型和原型链详解

JavaScript中原型和原型链详解

这篇文章主要介绍了JavaScript中原型和原型链详解,本文讲解了私有变量和函数、静态变量和函数、实例变量和函数、原型和原型链的基本概念,需要的朋友可以参考下javascript中的每个对象都有一个内置的属性prototype,Javascript中对象的prototype属性的解释是:返回对象类型原型的引用。

意思是是prototype属性保存着对另一个JavaScript 对象的引用,这个对象作为当前对象的父对象。

代码如下:A.prototype = new B();理解prototype不应把它和继承混淆。

A的prototype为B的一个实例,可以理解A将B 中的方法和属性全部克隆了一遍。

A能使用B的方法和属性。

这里强调的是克隆而不是继承。

可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。

继续看下面的分析:私有变量和函数在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。

代码如下:<script type="text/javascript">function Box(){var color = "blue";//私有变量var fn = function() //私有函数{}}</script>这样在函数对象Box外部无法访问变量color和fn,他们就变成私有的了:代码如下:var obj = new Box();alert(obj.color);//弹出undefinedalert(obj.fn);//同上静态变量和函数当定义一个函数后通过点号“.”为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数。

代码如下:<script type="text/javascript">function Obj(){};Obj.num = 72;//静态变量Obj.fn = function() //静态函数{}alert(Obj.num);//72alert(typeof Obj.fn)//functionvar t = new Obj();alert();//undefinedalert(typeof t.fn);//undefined</script>实例变量和函数在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问,js也能做到这样代码如下:<script type="text/javascript">function Box(){this.a=[]; //实例变量this.fn=function(){ //实例方法}}console.log(typeof Box.a); //undefinedconsole.log(typeof Box.fn); //undefinedvar box=new Box();console.log(typeof box.a); //objectconsole.log(typeof box.fn); //function</script>为实例变量和方法添加新的方法和属性代码如下:<script type="text/javascript">function Box(){this.a=[]; //实例变量this.fn=function(){ //实例方法}}var box1=new Box();box1.a.push(1);box1.fn={};console.log(box1.a); //[1]console.log(typeof box1.fn); //objectvar box2=new Box();console.log(box2.a); //[]console.log(typeof box2.fn); //function</script>在box1中修改了a和fn,而在box2中没有改变,由于数组和函数都是对象,是引用类型,这就说明box1中的属性和方法与box2中的属性与方法虽然同名但却不是一个引用,而是对Box对象定义的属性和方法的一个复制。

Javascript原型链的原理

Javascript原型链的原理

Javascript原型链的原理一、JavaScript原型链ECMAScript中描述了原型链的概念,并将原型链作为实现继承的主要方法。

其基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法。

在JavaScript中,用__proto__ 属性来表示一个对象的原型链。

当查找一个对象的属性时,JavaScript 会向上遍历原型链,直到找到给定名称的属性为止!比如现在有如下的代码:扩展Object类,添加Clone和Extend方法复制代码1 /*扩展Object类,添加Clone,JS实现克隆的方法*/2 Object.prototype.Clone = function(){3 var objClone;4 if (this.constructor == Object){5 objClone = new this.constructor();6 }else{7 objClone = new this.constructor(this.valueOf());8 }9 for(var key in this){10 if ( objClone[key] != this[key] ){11 if ( typeof(this[key]) == 'object' ){12 objClone[key] = this[key].Clone();13 }else{14 objClone[key] = this[key];15 }16 }17 }18 objClone.toString = this.toString;19 objClone.valueOf = this.valueOf;20 return objClone;21 }2223 /*扩展Object类,添加Extend方法来实现JS继承, 目标对象将拥有源对象的所有属性和方法*/24 Object.prototype.Extend = function (objDestination, objSource) {25 for (var key in objSource) {26 if (objSource.hasOwnProperty(key) && objDestination[key] === undefined) {27 objDestination[key] = objSource[key];28 }29 }30 return objDestination;31 }复制代码定义Person类1 /*定义一个Person类*/2 function Person(_name,_age){3 = _name;4 this.age = _age;5 }在JavaScript中,Object类是所有类的父类,所以Person类从Object类继承,继承了Object类的所有public属性和public方法,包括Object类新添加的Clone和Extend方法可以用如下的代码证明,Person类确实是继承了Object类复制代码1 document.write("<pre>");23 var p = new Person("孤傲苍狼",24);//创建一个人,名字是孤傲苍狼4 var cloneP = p.Clone();//p调用在Object类中定义的Clone方法来克隆自己,如果能得到一个cloneP,那就证明了Person类确实是继承了Object类,所以就拥有了Clone5 document.writeln("p是使用Person类以构造函数的方式创建出来的对象, = "++",p.age = "+p.age);6 document.writeln("cloneP是p调用Clone方法克隆出来的对象, = "++",cloneP.age = "+cloneP.age);7 document.writeln("cloneP对象和p对象是两个相互独立的对象,这两个对象的内存地址肯定是不相等,p == cloneP的结果是:"+(p == cloneP));8 ="白虎神皇";//修改cloneP的名字9 document.writeln("cloneP的name被修改了, = "+);10 document.writeln("cloneP的name修改了,但是不影响到p, = "+);1112 document.write("</pre>");复制代码运行结果:那么Person类通过神马方式来继承Object类的呢,是使用原型(prototye)的方式继承的:1 /*定义一个Person类*/2 function Person(_name,_age){3 = _name;4 this.age = _age;5 }6 Person.prototype = new Object();//让Person类继承Object类由于JavaScript规定,任何类都继承自Object类,所以"Person.prototype = new Object();//让Person类继承Object类"即使我们不写,我猜想JavaScript引擎也会自动帮我们加上这句话,或者是使用"Person.prototype = Object.prototype;"这种方式,让Person类去继承Object 类。

JS中原型链的理解

JS中原型链的理解

JS中原型链的理解new操作符具体⼲了什么呢?其实很简单,就⼲了三件事情。

1var obj = {};2 obj.__proto__ = Base.prototype;3 Base.call(obj);第⼀⾏,我们创建了⼀个空对象obj第⼆⾏,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象第三⾏,我们将Base函数对象的this指针替换成obj,然后再调⽤Base函数,于是我们就给obj对象赋值了⼀个id成员变量,这个成员变量的值是”base”,关于call函数的⽤法。

在谈原型链之前,我们⾸先要了解⾃定义函数与 Function 之间是什么关系,⽽构造函数、原型和实例之间⼜存在什么千丝万缕的关系呢?其实,所有的函数都是 Function 的实例。

在构造函数上都有⼀个原型属性 prototype,该属性也是⼀个对象;那么在原型对象上有⼀个constructor 属性,该属性指向的就是构造函数;⽽实例对象上有⼀个 _proto_ 属性,该属性也指向原型对象,并且该属性不是标准属性,不可以⽤在编程中,该属性⽤于浏览器内部使⽤。

1 // _proto_2 在函数⾥有⼀个属性prototype3 由该函数创建的对象默认会连接到该属性上4 //prototype 与 _proto_ 的关系5 _proto_是站在对象⾓度来说的6 prototype 是站在构造函数⾓度来说的 下⾯,我们来看图说话。

1、构造函数、原型和实例之间的关系①+Object ②+Function+Object+Array 了解这些之后,我们再来讨论什么是原型链。

说⽩了,其实就是有限的实例对象和原型之间组成有限链,就是⽤来实现共享属性和继承的。

下⾯,我们看代码说话。

1 var obj = new Object();2 对象是有原型对象的3 原型对象也有原型对象4 obj._proto_._proto_._proto_5 原型对象也有原型对象,对象的原型对象⼀直往上找,会找到⼀个null6 // 原型链⽰例7 var arr = [];8 arr -> Array.prototype ->Object.prototype -> null9 var o = new Object();10 o -> Object.prototype -> null;function Foo1(){1 = '1';}function Foo2(){2 = '2';}Foo2.prototype = new Foo1();function Foo3(){ = '3';}Foo3.prototype = new Foo2();var foo3 = new Foo3();console.dir(foo3); 接下来就是继承问题了。

深入浅出理解javaScript原型链

深入浅出理解javaScript原型链

深入浅出理解javaScript原型链
这篇文章是关于深入浅出理解javaScript的内容,以下就是该内容的详细介绍。

 对于javascript原型链,以前都觉得是个很深的东西,一直没有理解很明白,今天看了一些介绍后,发现这张图,表示再没有什幺语言能比这张图说得清楚了。

 javascript的原型链有显式和隐式两种:
 显式原型链:即我们常见的prototype;
 隐式原型链:在一般环境下无法访问,即不可见,在FireFox下可以通过__proto__方式访问;隐式原型链用于javascript引擎内部对原型链的搜寻,通过显示原型链来设置;
 一、prototype和__proto__的概念
 prototype是函数的一个属性(每个函数都有一个prototype属性),这个属性是一个指针,指向一个对象。

它是显示修改对象的原型的属性。

 __proto__是一个对象拥有的内置属性(请注意:prototype是函数的内置属性,__proto__是对象的内置属性),是JS内部使用寻找原型链的属性。

js原型链原理

js原型链原理

js原型链原理先附上原型链的图,能看懂的本⽂就没必要看了,看不懂的可以带着疑问看⽂章⼀、构造函数什么是构造函数:当⼀个普通函数创建⼀个类对象是,那么就程它为构造函数。

特点:默认⾸字母⼤写使⽤new关键字来调⽤,并返回⼀个实例对象内部使⽤this来构造属性和⽅法this指向返回的新对象function Person(name){ = namethis.eat = function(){console.log("⽅法")}}let per = new Person("⼩⼩")per.eat()⼆、原型为什么需要原型:在⼀些场景中,⽐如⼈类⾏为有些要打游戏,有些要上学,有些要⼯作,但同时他们都需要吃饭和睡觉,但如果把每个⼈吃饭睡觉私有化使⽤的话就有点浪费内存,这时候就可以把这些每个⼈都需要做的⾏为统⼀拿出来放到⼀个公共的空间,每个⼈都有权限访问它,这样就可以节省内存。

⽽实现共享的,这个时候就⽤到了原型 prototype。

什么是原型:每个函数对象都有⼀个prototype属性,这个属性的指向被称为该函数对象的原型对象,简称原型。

function Person(name){ = name// this.eat = function(){// console.log("饭")// }}Person.prototype={constructor:Person, //修改constructor的指向eat:function(){console.log("饭")},sleep:function(){console.log("睡觉")}}var per = new Person("⼩⼩")var Per = new Person("⼤⼤")console.log(per.eat === Per.eat) //true以上案例我们看到Person的⽅法写到原型中的时候,实例化后的对象拿到的⽅法是共享的。

JavaScript中原型和原型链详解

JavaScript中原型和原型链详解

JavaScript中原型和原型链详解javascript中的每个对象都有⼀个内置的属性prototype,Javascript中对象的prototype属性的解释是:返回对象类型原型的引⽤。

意思是是prototype属性保存着对另⼀个JavaScript对象的引⽤,这个对象作为当前对象的⽗对象。

复制代码代码如下:A.prototype = new B();理解prototype不应把它和继承混淆。

A的prototype为B的⼀个实例,可以理解A将B中的⽅法和属性全部克隆了⼀遍。

A能使⽤B的⽅法和属性。

这⾥强调的是克隆⽽不是继承。

可以出现这种情况:A的prototype是B的实例,同时B的prototype也是A的实例。

继续看下⾯的分析:私有变量和函数在函数内部定义的变量和函数,如果不对外提供接⼝,外部是⽆法访问到的,也就是该函数的私有的变量和函数。

复制代码代码如下:<script type="text/javascript">function Box(){var color = "blue";//私有变量var fn = function() //私有函数{}}</script>这样在函数对象Box外部⽆法访问变量color和fn,他们就变成私有的了:复制代码代码如下:var obj = new Box();alert(obj.color);//弹出 undefinedalert(obj.fn);//同上静态变量和函数当定义⼀个函数后通过点号 “.”为其添加的属性和函数,通过对象本⾝仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量和静态函数。

复制代码代码如下:<script type="text/javascript">function Obj(){};Obj.num = 72;//静态变量Obj.fn = function() //静态函数{}alert(Obj.num);//72alert(typeof Obj.fn)//functionvar t = new Obj();alert();//undefinedalert(typeof t.fn);//undefined</script>实例变量和函数在⾯向对象编程中除了⼀些库函数我们还是希望在对象定义的时候同时定义⼀些属性和⽅法,实例化后可以访问,js也能做到这样复制代码代码如下:<script type="text/javascript">function Box(){this.a=[]; //实例变量this.fn=function(){ //实例⽅法}}console.log(typeof Box.a); //undefinedconsole.log(typeof Box.fn); //undefinedvar box=new Box();console.log(typeof box.a); //objectconsole.log(typeof box.fn); //function</script>为实例变量和⽅法添加新的⽅法和属性复制代码代码如下:<script type="text/javascript">function Box(){this.a=[]; //实例变量this.fn=function(){ //实例⽅法}}var box1=new Box();box1.a.push(1);box1.fn={};console.log(box1.a); //[1]console.log(typeof box1.fn); //objectvar box2=new Box();console.log(box2.a); //[]console.log(typeof box2.fn); //function</script>在box1中修改了a和fn,⽽在box2中没有改变,由于数组和函数都是对象,是引⽤类型,这就说明box1中的属性和⽅法与box2中的属性与⽅法虽然同名但却不是⼀个引⽤,⽽是对Box对象定义的属性和⽅法的⼀个复制。

谈谈我对js原型链的理解

谈谈我对js原型链的理解

谈谈我对js原型链的理解想要学习 “原型链” 必须要认识什么是 “原型” 和 “原型链”先理解⼀下普通的继承和原型的区别,下⾯写⼀段js代码来帮助理解:var Animal = function(){ // 动物抽象类 ; this.age; this.sex; this.skill = function(){}; this.die = function(){};};var Dog = function(){};var Cat = function(){};Dog = new Animal(); // 这⾥Dog就是具体的动物对象它拥有动物的公有属性【 name, age, sex, func:sikll, func:die 】Cat = new Animal(); // 这⾥Cat也是具体的动物对象它呢也拥有动物的公有属性【 name, age, sex, func:sikll, func:die 】Dog 和 Cat 同时继承了 Animal 也就是说他们都拥有【 name, age, sex, func:sikll, func:die 】这些属性。

那么他们和原型的区别是什么呢?区别就是:不管是 Dog继承或是Cat继承⼜或者是其它具体类继承了Animal ,各⾃都会复制⼀份 Animal内部的结构(⼤脑⾥构建⼀下这样的场景),试想⼀下,如果有⼏⼗个上百个具体类继承了Animal 难道还要复制⼏⼗个上百个Animal内部结构吗?那怎么解决上⾯多复制的问题呢?那这就是“原型”要解决的问题咯,对的就是说使⽤原型后不管有多少个类继承Animal 它内部的结构只复制⼀次。

够明⽩了吗?这就是原型的概念!我们把上⾯的代码改动⼀下,看看原型的写法:var Animal = function(){ // 动物抽象类 ; this.age; this.sex;};Animal.prototype.skill = function(){};Animal.prototype.die = function(){};var Dog = function(){};var Cat = function(){};Dog.prototype = new Animal();Cat.prototype = new Animal();这样写就可以继承Animal类下的所有字段和⽅法,但是这⾥有个⼩问题,就是说 skill 和 die 可以正常调⽤,因为他们是函数。

Javascript讲解系列之一Prototype原型链

Javascript讲解系列之一Prototype原型链

Javascript讲解系列之⼀Prototype原型链以前没有写博客的习惯,许多的技术积累都是⾃⼰稍微总结⼀下,很少共享,并⾮⾃私,⽽是⼯作⽐较忙,前⼏天接到⼀个电话⾯试不理想,才发现公司所⽤的DOJO并不被外⾯⼴泛接受,故⽽决定把⾃⼰所学分享出来,为夯实基础,也为与外界交流思想,形成⼀种渠道,如需联系,请发送⾄邮箱:diydyq@。

今天写Javascript系列之第⼀篇:Prototype原型链。

在软件园⾥随便拉⼀个码农估计都会写JS,⼤部分也知道JS是基于原型的语⾔,但是如果问及JS原⽣对象(Object,Function,Array,Date等)的这个原型链长什么样⼦?估计能回答出来的⼈就少了,我开始也⾮常糊涂,后来决⼼⼀定要好好搞⼀下,花了2天功夫基本算是明⽩了,分享如下:测试环境:Firefox、Firebug;为做好铺垫,按顺序解释如下概念:1)类型、原⽣类型、对象类型(types、primitive types、object types)不像我们在学习JAVA时,被告知JAVA是完全OOP的语⾔:class是⼀类具有共同特点的物体的抽象,object是某个class下具体的⼀个实例,Object类是所有类的顶层⽗类,对Java的认知是从类与对象开始的;Javascript则不然,它是从类型(type)开始,在各类语⾔中遇到的number,string, boolean, object, function,array等都属于类型。

这些类型在JS中分为两⼤类:原⽣类型与对象类型,原⽣类型包括:number,string, bool, null, undefined;剩下的⾮原⽣类型对象都属于对象类型,包括:object, array, function等,这⾥的object专指具有属性(attribute)的对象,在Firebug中的代码⽰例如下:function log(){ console && console.log.apply(console, arguments); };var opts = Object.prototype.toString;// 1) primitive typeslog(typeof 1); // numberlog(typeof ""); // stringlog(typeof false); // booleanlog(typeof undefined); // undefinedlog(typeof null); // object null是个特列,属于原⽣类型;log(null instanceof Object); // false// 2) object types.log(typeof new Object); // objectlog(typeof new Function); // functionlog(typeof new Array); // objectlog(opts.call(new Object)); // [object Object]log(opts.call(new Function)); // [object Function]log(opts.call(new Array)); // [object Array]判断某个值是什么⼤的类型没有意义,往往需要判断它是什么原⽣类型或者对象类型:判断原⽣类型,可以使⽤typeof关键字;判断对象类型,可以使⽤toString()⽅法;2)prototype与__proto__的区别两者都是对象类型的属性,并⾮所有的对象类型都有prototype属性,⼀般只有function对象才有prototype属性(除⾮主动赋值),它指向的是⼀个对象,将来会被多个该function的实例所继承(或者说该对象处于多个实例的原型链上);__proto__才是真正的原型链的实际指针,然⽽许多浏览器并不对外公开这个属性,Firefox暴露出这⼀属性,仅供开发⼈员理解,但不推荐开发中使⽤。

js原型链(转)

js原型链(转)

js原型链(转)1.1 理解原型链JavaScript中⼏乎所有的东西都是对象,我们说数组是对象、DOM节点是对象、函数等也是对象,创建对象的Object也是对象(本⾝是构造函数),那么有⼀个重要的问题:对象从哪⾥来?这是⼀句废话,对象当然是通过⼀定⽅式创建出来的,根据实际类型不同,对象的创建⽅式也千差万别。

⽐如函数,我们可以声明函数、使⽤Function构造函数创建等,⽐如数组,我们可以直接通过var arr = [] 的⽅式创建空数组,也可以通过new Array的⽅式创建,⽐如普通的对象,我们可以字⾯量创建、使⽤内置构造函数创建等等,花样太多了,以⾄于我们学习的时候头昏脑涨、不得要领。

其实,归根结底所有“类型”的对象都可以认为是由相应构造函数创建出来的。

函数由Function构造函数实例化⽽来,普通对象由Object构造函数实例化⽽来,数组对象由Array构造函数实例化⽽来,⾄于Object | Array | Function等他们本⾝是函数,当然也有⾃⼰的构造函数。

理解了上⾯⼀点,那么接下来我们在理解原型链的时候就会容易得多。

请看刺激的推导过程前提所有对象都由构造函数实例化⽽来,构造函数默认拥有与之相关联的原型对象❒①构造函数的原型对象也是对象,因此也有⾃⼰的构造函数❒②构造函数原型对象的构造函数,也有与之相关连的原型对象❒③构造函数原型对象的原型对象(__proto__)也有⾃⼰的构造函数,其也拥有关联的原型对象☞以上就形成了⼀种链式的访问结构,是为原型链。

其实构造函数也是对象,所以构造函数本⾝作为对象⽽⾔也有⾃⼰的构造函数,⽽这个构造函数也拥有与之相关联的原型对象,以此类推。

那么,这就是另⼀条原型链了。

综上,我们可以得出原型链并不孤单的结论。

1.2 原型链结构现在我们基本上把原型链的由来说清楚了,那么接下来通过具体的代码来分析原型链的整体结构。

⽰例代码1 //01 ⾃定义构造函数Person和Animal2 function Person() {}3 function Animal() {}4 //02 使⽤构造函数创建实例对象5 var p1 = new Person();6 var p2 = new Person();7 var a = new Animal();8 //03 创建数组对象9 var arrM = ["demoA","demoB"];上⾯的代码⾮常简单,其中p1,p2和a它们是⾃定义构造函数的实例化对象。

一张图彻底理解Javascript原型链

一张图彻底理解Javascript原型链

⼀张图彻底理解Javascript原型链代码讲解⽤到的代码很简单,如下function Foo(){//属性和⽅法}var f1 = new Foo();var f2 = new Foo();var o1 = new Object();var o2 = new Object();基础了解⼀切皆对象,对象⼜可以分为两类:1. 普通对象,除了函数对象之外的对象都是,包括new函数对象()产⽣的实例,普通对象没有prototype,也就没有继承和原型链⼀说。

2. 函数对象,包括两种:由function创造出来的函数:function f1() {} // 匿名函数var f2 = function() {}var f3 = new Function('x','console.log(x)');// 以上都是函数对象系统内置的函数对象:Function、Object、Array、String、Number ,Function其实充当了函数对象的构造器,⽐如Object对象的构造源码其实是Function Object() {[native code]}的形式,这⼀点对于理解原型链很重要。

进⼊正题上图从结构上分为实例对象、Functions函数对象、prototype原型对象三部分,图中f1、f2的原型链我特意标成了红⾊,Foo的原型链为紫⾊。

每个对象都有__proto__属性,⽤于储存继承得来的⽅法和属性;每个函数对象都有prototype属性,⽤于继承,将其中定义的属性和⽅法传递给‘后代’(⽐如实例化)。

如何实现原型继承f1为何有Foo、Object的原型⽅法,其实就是通过原型链继承。

继承的过程可以表⽰为f1.__proto__ = Foo.prototype,即对象.__proto__ = 构造器.prototype。

new实例实现继承的过程其实与上⾯原理相同,new的过程可以拆解为下⾯⼏个步骤:var temp = {};temp.__proto__ = Foo.prototype; // 原型继承var f1 = Foo.call(temp);return f1;找出原型链1) f1的原型链(红⾊虚线)。

带你理解JavaScript原型原型链

带你理解JavaScript原型原型链

带你理解JavaScript原型原型链⽬录⼀、原型、原型链相等关系理解⼆:原型、原型链的意思何在看完这篇⽂章,你会发现,原型、原型链原来如此简单!上⾯经典的原型链相等图,根据下⽂的学习,你会轻易掌握。

⼀、原型、原型链相等关系理解⾸先我们要清楚明⽩两个概念:js分为函数对象和普通对象,每个对象都有__proto__属性,但是只有函数对象才有prototype属性Object、Function都是js内置的函数, 类似的还有我们常⽤到的Array、RegExp、Date、Boolean、Number、String这两个概念⼤家跟我⼀起读三遍并记住,后⾯会⽤到那么__proto__和prototype到底是什么,两个概念理解它们属性__proto__是⼀个对象,它有两个属性,constructor和__proto__ ;原型对象prototype有⼀个默认的constructor属性,⽤于记录实例是由哪个构造函数创建;这两个概念⼤家跟我⼀起读三遍并记住,后⾯会⽤到有以下构造函数Person,他的原型上有所属国属性motherland='China'function Person(name, age){ = name;this.age = age;}Person.prototype.motherland = 'China'通过new Person()创建的person01实例let person01 = new Person('⼩明', 18);js之⽗在设计js原型、原型链的时候遵从以下两个准则Person.prototype.constructor == Person // **准则1:原型对象(即Person.prototype)的constructor指向构造函数本⾝**person01.__proto__ == Person.prototype // **准则2:实例(即person01)的__proto__和原型对象指向同⼀个地⽅**这两个准则⼤家跟我⼀起读三遍并记住,后⾯会⽤到记住以上四个概念两个准则,任何原型链相等判断都能判断正确;⼤家可以对照上图,看看⾃⼰概念准则是否弄清楚了,⼀定要对照上图哦// 从上⽅ function Foo() 开始分析这⼀张经典之图function Foo()let f1 = new Foo();let f2 = new Foo();f1.__proto__ = Foo.prototype; // 准则2f2.__proto__ = Foo.prototype; // 准则2Foo.prototype.__proto__ = Object.prototype; // 准则2 (Foo.prototype本质也是普通对象,可适⽤准则2)Object.prototype.__proto__ = null; // 原型链到此停⽌Foo.prototype.constructor = Foo; // 准则1Foo.__proto__ = Function.prototype; // 准则2Function.prototype.__proto__ = Object.prototype; // 准则2 (Function.prototype本质也是普通对象,可适⽤准则2)Object.prototype.__proto__ = null; // 原型链到此停⽌// **此处注意Foo 和 Function的区别, Foo是 Function的实例**// 从中间 Function Object()开始分析这⼀张经典之图Function Object()let o1 = new Object();let o2 = new Object();o1.__proto__ = Object.prototype; // 准则2o2.__proto__ = Object.prototype; // 准则2Object.prototype.__proto__ = null; // 原型链到此停⽌Object.prototype.constructor = Object; // 准则1Object.__proto__ = Function.prototype // 准则2 (Object本质也是函数);// 此处有点绕,Object本质是函数,Function本质是对象Function.prototype.__proto__ = Object.prototype; // 准则2 (Function.prototype本质也是普通对象,可适⽤准则2)Object.prototype.__proto__ = null; // 原型链到此停⽌// 从下⽅ Function Function()开始分析这⼀张经典之图Function Function()Function.__proto__ = Function.prototype // 准则2Function.prototype.constructor = Function; // 准则1由此可以得出结论:除了Object的原型对象(Object.prototype)的__proto__指向null,其他内置函数对象的原型对象(例如:Array.prototype)和⾃定义构造函数的__proto__都指向Object.prototype, 因为原型对象本⾝是普通对象。

认识javascript中的原型和原型链

认识javascript中的原型和原型链

认识javascript中的原型和原型链原型和原型链是javascript中⾮常重要的概念,下⾯让我们来认识⼀下这两个熟悉的陌⽣⼈。

原型概念:⽆论何时,只要创建⼀个函数,就会按照规则为这个函数创建⼀个prototype属性,prototype属性指向的对象也就是原型对象。

每次调⽤这个函数创建⼀个新实例,这个实例内部指针([[prototype]])就会被赋值为这个函数的原型对象,由于javascript脚本中没有设置可以访问[[prototype]]特性的标准模式,所以Firefox,Safari和Choreme会在每个对象上暴露⼀个__proto__属性,通过这个属性就可以访问到对象的原型。

作⽤:通过对象的原型,我们可以获取到这个对象有哪些属性,并在实例化对象时,直接拥有这些属性。

下⾯,我们同样通过例⼦来理解原型的概念。

function Person() { //构造函数} = "张三";Person.prototype.age = "18";Person.prototype.sex = "man";const person = new Person(); //实例1 = '李四'const person2 = new Person(); //实例2console.log(person.__proto__ === Person.prototype) //trueconsole.log(person.__proto__ === person2.__proto__ ) //true例⼦中,我们定义了构造函数Person,并给Person的原型对象上设置了三个属性。

同时也通过Person函数构建了两个实例person和person2。

例⼦的输出结果都是true,所以我们可以看出,实例化的对象的__proto__属性是指向构造函数的prototype属性,所以这person.__proto__和 Person.prototype是全等的。

JS原型和原型链原理与用法实例详解

JS原型和原型链原理与用法实例详解

JS原型和原型链原理与⽤法实例详解本⽂实例讲述了JS原型和原型链原理与⽤法。

分享给⼤家供⼤家参考,具体如下:Javascript语⾔的继承机制⼀直很难被⼈理解。

它没有"⼦类"和"⽗类"的概念,也没有"类"(class)和"实例"(instance)的区分,全靠⼀种很奇特的"原型链"(prototype chain)模式,来实现继承。

Brendan Eich设计javascript之初是为了实现⽹页与浏览器之间交互的⼀种简单的脚本语⾔如果真的是⼀种简易的脚本语⾔,其实不需要有"继承"机制。

但是,Javascript⾥⾯都是对象,必须有⼀种机制,将所有对象联系起来。

所以,Brendan Eich最后还是设计了"继承"。

背景介绍1.构造函数构造函数,是⼀种特殊的⽅法。

主要⽤来在创建对象时初始化对象。

每个构造函数都有prototype(原型)属性2.原型模式每个函数都有prototype(原型)属性,这个属性是⼀个指针,指向⼀个对象,这个对象的⽤途是包含特定类型的所有实例共享的属性和⽅法,即这个原型对象是⽤来给实例共享属性和⽅法的。

⽽每个实例内部都有⼀个指向原型对象的指针。

原型链每个构造函数都有⼀个原型对象,原型对象都包含⼀个指向构造函数的指针,⽽实例都包含指向原型对象内部的指针。

我们让原型对象的实例(1)等于另⼀个原型对象(2),此时原型对象(2)将包含⼀个指向原型对象(1)的指针,再让原型对象(2)的实例等于原型对象(3),如此层层递进就构成了实例和原型的链条,这就是原型链的概念构造函数构造函数,是⼀种特殊的⽅法。

主要⽤来在创建对象时初始化对象。

即为对象变量赋初始值。

每个构造函数的实例都将共享构造函数的初始值。

构造函数的出现是为了解决使⽤Object构造函数和字⾯量表⽰法不⽅便创建⼤量重复对象的问题。

原型链知识点

原型链知识点

原型链知识点
原型链是JavaScript中一种实现继承的机制,它是由对象的属
性和方法组成的层级结构。

每个对象都有一个原型对象,对象通过原型对象来继承属性和方法。

在JavaScript中,当访问对象的属性或调用对象的方法时,JavaScript引擎会首先在对象本身查找,如果找不到该属性或
方法,则会沿着原型链向上查找,直到找到或者到达原型链的末端null为止。

原型链的构成如下:
1. 对象:每个对象都有一个原型对象,通过`__proto__`属性指
向它的原型对象。

2. 原型对象:每个构造函数都有一个原型对象,通过
`prototype`属性指向它的原型对象。

原型对象是一个普通的对象,它包含了该构造函数的实例共享的属性和方法。

3. 构造函数:每个对象都有一个构造函数,通过`constructor`
属性指向它的构造函数。

当访问对象的属性或方法时,如果对象本身没有该属性或方法,则会沿着原型链向上查找。

比如,如果对象A的原型对象上
有属性a,则对象A可以通过`A.a`来访问该属性。

原型链的顶端是Object的原型对象,它的原型对象为nll,表
示原型链的末端。

任何对象的原型链最终都会到达Object的
原型对象。

使用原型链可以实现对象之间的继承关系,类似于传统的面向对象编程语言中的继承。

子对象通过原型链继承父对象的属性和方法,可以减少代码的冗余,提高代码的复用性。

同时,可以通过在原型对象上添加属性和方法,实现对所有子对象的统一修改和扩展。

原型和原型链的理解

原型和原型链的理解

原型和原型链的理解原型和原型链是JavaScript言中两个比较重要的概念,他们可以影响到 JavaScript序的行为和性能,对 JavaScript序员的设计和编程具有重要的意义。

本文将从原型和原型链的定义、特性及其模式、性能优势等方面来讨论这两个概念。

首先,原型和原型链的定义。

原型是一种特殊的对象,它可以用来存储相关函数和方法,这些函数和方法可以用于构建新的对象。

原型链是一种让对象继承属性和方法的机制,它能够使用原型来构建一系列模型,为每个模型分配新的属性和方法。

这样,它让开发者可以通过继承自己创造的原型,为程序很好地节省时间、空间以及资源。

接着,原型和原型链的特性及其模式。

首先,原型链的特点是“继承”,也就是对象可以从另一个对象继承属性和方法。

其次,原型模式是一种创建对象的设计模式,它可以让一个对象可以被多个对象继承,从而使数据和行为可复用。

最后,原型和原型链也可以与其他类似的设计模式,如组合模式,外观模式,迭代器模式等进行结合,以达到更好的设计效果。

此外,原型模式有很好的性能优势,特别是在实现 JavaScript象的继承的情况下,原型链的性能极其优异。

由于原型链使用的是闭包,而不是类来实现继承,因此可以实现模块继承,这可以避免开发者在属性和方法之间进行不必要的重复声明和重复分配。

这就意味着每组新的属性和方法仅会被声明和分配一次,这会大大节省内存开销。

总的来说,原型和原型链是 JavaScript言中的重要概念,它们的作用不仅仅体现在实现对象继承和面向对象复用,而且还可以提高JavaScript序的性能。

理解原型和原型链对于 JavaScript序员设计和编程具有重要重要意义,有助于正确使用这些概念,以达到最佳的设计效果。

JavaScript原型链以及Object,Function之间的关系

JavaScript原型链以及Object,Function之间的关系

JavaScript原型链以及Object,Function之间的关系JavaScript⾥任何东西都是对象,任何⼀个对象内部都有另⼀个对象叫__proto__,即原型,它可以包含任何东西让对象继承。

当然__proto__本⾝也是⼀个对象,它⾃⼰也有⾃⼰的__proto__,这样⼀级⼀级向上,就构成了⼀个__proto__链,即原型链。

当然原型链不会⽆限向上,它有个终点,可以称为原型链的顶端,或者root,它是⼀个特殊的对象,它的__proto__为null。

obj.__proto__.__proto__......__proto__ === null;但是对象并不是凭空产⽣的,它⼀般是某⼀个class,或者确切说是构造函数的实例。

JavaScript和其它⾯向对象的语⾔不太⼀样,它没有所谓的class,⽽是⽤函数来模拟class。

定义了⼀个函数,实际上就定义了⼀个class,函数本⾝就是class的constructor,例如:function foo() {}var a = new foo();这⾥创建了⼀个对象a,是foo的⼀个实例。

既然a是⼀个对象,它就有原型__proto__,那a的__proto__是怎么设定的?这⾥就引出了prototype,它是函数才有的⼀个属性,也是⼀个对象,⼀个函数创建的实例的__proto__就指向这个函数的prototype。

所以a的__proto__被设定为foo.prototype,即:a.__proto__ === foo.prototype;当然foo.prototype也是个对象,它⾃然也有__proto__,默认指向Object.prototype,即:foo.prototype.__proto__ === Object.prototype;⽽Object.prototype已经没有原型了,它的__proto__是null。

这是JavaScript⾥⼀个很特殊的对象,它就是原型链的顶端。

原型链知识点

原型链知识点

原型链知识点原型链是JavaScript中一个重要的概念,它对于理解JavaScript的继承机制和对象属性查找有着至关重要的作用。

本文将以原型链为主线,介绍原型链的定义、原型和原型链的关系、原型链的查找过程以及一些相关的注意事项。

1. 原型链的定义原型链是JavaScript中实现继承的一种机制,它通过将对象与原型对象关联起来,实现对属性和方法的继承。

每个对象都有一个原型对象,而原型对象也可以拥有自己的原型对象,这样就形成了一个链式的结构,从而构成了原型链。

2. 原型和原型链的关系在JavaScript中,每个对象都有一个特殊的属性[[Prototype]],它指向该对象的原型对象。

原型对象也是一个对象,同样拥有自己的[[Prototype]]属性,这样就形成了一个链式的结构,即原型链。

3. 原型链的查找过程当访问一个对象的属性或方法时,JavaScript引擎会首先在该对象自身的属性和方法中查找,如果找不到,就会沿着原型链往上查找,直到找到匹配的属性或方法,或者到达原型链的末尾(即Object.prototype)为止。

4. 原型链的创建在JavaScript中,通过构造函数创建的对象都有一个默认的原型对象,即构造函数的prototype属性。

我们可以通过修改原型对象的属性和方法,来给所有通过该构造函数创建的对象添加共享的属性和方法。

当我们访问一个对象的属性或方法时,如果该对象本身没有这个属性或方法,就会去原型对象中查找。

5. 原型链的注意事项在使用原型链时,需要注意以下几点:- 修改原型对象的属性和方法会立即反应到所有通过该构造函数创建的对象上,因此要谨慎修改原型对象。

- 在通过构造函数创建对象时,如果没有使用new关键字,那么该对象将不会拥有自己的原型对象,而会直接继承构造函数的原型对象。

- 在原型链上层的原型对象中定义的属性和方法会被下层的原型对象所共享,因此需要注意避免命名冲突。

- 原型链的查找是一种自上而下的过程,因此如果原型链过长,可能会对性能产生影响,需要合理设计原型链的结构。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

var foo = { x: 10, y: 20 };
当我不指定__proto__的时候,foo也会预留一个这样的属性, 如果有明确的指向,那么这个链表就链起来啦。 很明显,下图中b和c 共享a的属性和方法,同时又有自己的私有属性。
__proto__默认的也有指向。它指向的是最高级的object.prototype,而object.prototype的__proto__为空。 复制代码代码如下: var ห้องสมุดไป่ตู้ = { x: 10, calculate: function (z) { return this.x + this.y + z } }; var b = { y: 20, __proto__: a }; var c = { y: 30, __proto__: a }; // call the inherited method b.calculate(30); // 60
js原型链原理看图说明
任何一个对象都有一个prototype的属性,在js中可以把它记为:__proto__ 当初ECMAscript的发明者为了简化这门语言,同时又保持继承的属性,于是就设计了这个链表。。 在数据结构中学过链表不,链表中有一个位置相当于指针,指向下一个结构体。 于是乎__proto__也一样,每当你去定义一个prototype的时候,相当于把该实例的__proto__指向一个结构体,那么这个被指向结构体就 称为该实例的原型。 文字说起来有点儿绕,看图说话 复制代码代码如下:
理解了__proto__这个属性链接指针的本质。。再来理解constructor。 当定义一个prototype的时候,会构造一个原形对象,这个原型对象存储于构造这个prototype的函数的原形方法之中. 复制代码代码如下:
function Foo(y){ this.y = y ; } Foo.prototype.x = 10; Foo.prototype.calculate = function(z){ return this.x+this.y+z; }; var b = new Foo(20); alert(b.calculate(30));
相关文档
最新文档