JavaScript原型与原型链学习笔记

一.什么是原型?
原型是一个对象,其他对象可以通过它实现属性继承。
简单的说就是任何一个对象都可以成为原型

prototype属性: 我们创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象包含可以有特定类型的所有实例共享的属性和方法。这个对象就是原型对象(也就是某个对象的原型所引用的对象)。
1.总之只要创建了函数,该函数都有一个prototype属性,指向函数的原型对象。

如上图,Person是一个函数,右侧的方框就是它的原型。

2.默认情况下所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针。

简单来说prototype的属性值是一个对象(属性的集合,我们可以给他设置各种值),默认的只有一个叫做constructor的属性,指向这个函数本身。

下面就是一个原型对象的例子:

 1 function Person() {
 2
 3         }
 4         Person.prototype.name="花花";
 5         Person.prototype.sex="女";
 6         Person.prototype.showName=function(){
 7                 console.log(‘我的名字叫:‘+this.name+‘我是:‘+this.sex+‘的‘);
 8             }
 9
10         var p1=new Person();
11
12         p1.showName();

所以在这个例子里:原型对象Person.prototype的constructor属性指向Person。

3.原型对象的内部还包括一个指针__proto__指向构造函数的原型对象。每个对象都有一个__proto__属性。
注意:Object.prototype是一个特例——它的__proto__指向的是null

这个__proto__是一个隐藏的属性,在FF,Safari和Ghrome支持。

如上面的例子,Person是一个函数,p1对象是从Person函数new出来的,这样p1对象就可以调用Person.prototype中的属性。因为每个对象都有一个隐藏的属性——“__proto__”,这个属性引用了创建这个对象的函数的prototype。即:p1.__proto__ === Person.prototype
下面在上面的例子中添加下面代码来验证一下:

1 console.log(p1.__proto__ === Person.prototype);//ture

结果为true证明他们是相等的

简单分析一下:构造函数Person有一个prototype的属性对象(即:Person.prototype),其中prototype属性对象中会包括__proto__,constructor(构造函数)指向构造函数,还有一些添加的属性。创建构造函数的实例对象p1,p1会有__proto__属性,指向其原型Person.prototype。

看看下面的图捋一捋

那么问题来了,之前我们说每个对象都有一个__proto__属性,函数也是一种对象,那么函数自然也有__proto__了,函数也是被创建出来的。谁创建了函数呢?那就是——Function——注意这个大写的“F”。

演示代码如下:

1 function fn1(a,b) {
2             return a+b;
3     }
4     console.log(fn1(2,6));
5
6     var fn2=new Function("a","b","return a+b")
7     console.log(fn2(6,6));

以上代码中,第一种方式是比较传统的函数创建方式,第二种是用new Functoin创建。注意:不推荐用第二种方式

综上所述:第一个例子中的构造函数Person也是一个对象,所以它也存在__proto__属性,指向它的原型Function.prototype。

(根据这个图用下面的方法可自行验证)

Function.prototype指向的对象也是一个普通的被Object创建的对象,所以Function.prototype指向的对象,它的__proto__也指向Object.prototype

验证一下:

1 console.log(Function.prototype.__proto__);//结果是Object {}

判断原型的方法有下面三种:

1         console.log(Object.getPrototypeOf(Person));
2         console.log(Object.__proto__);//函数原型对象
3         console.log(Person.constructor.prototype);

Object.getPrototypeOf()方法是ECMAScript5新加的,主流浏览才可以用。

总结一下:每个函数都有一个prototype,即原型(指向函数的原型对象)。每个对象都有一个__proto__属性(指向构造函数的原型对象),可成为隐式原型。
那么原型就是构造函数的实例对象的__proto__属性指向的构造函数的原型对象。

二.原型链

原型链:访问一个对象的属性时,先在基本属性中查找,如果没有,再沿着__proto__这条链向上找,这就是原型链

下面是一个原型链的例子:

 1 function Person(name,sex) {
 2             this.name=name;
 3             this.sex=sex;
 4         }
 5
 6         Person.prototype.show=function(){
 7                 console.log(‘我的名字叫:‘+this.name+‘我是:‘+this.sex+‘的‘);
 8             }
 9         Person.prototype.showName=function(){
10                 console.log(‘名字:‘+this.name);
11             }
12
13         function Worker(name,sex,job){
14             Person.call(this,name,sex);//继承Person属性
15             this.job=job;
16         }
17         Worker.prototype=Person.prototype;//这是原型链(通往父级的一条链上传递)
18         Worker.prototype.showJob=function(){//子级添加新方法
19             console.log(this.job);
20         }
21         Worker.prototype.show=function(){
22                 console.log(‘名字:‘+this.name+‘性别:‘+this.sex+‘工作:‘+this.job);
23             }
24         var p2=new Worker(‘mumu‘,‘女‘,‘student‘);
25         p2.showName();
26         p2.show();

分析下例子:创建Person函数,并在Person的原型对象上创建show和showName函数

创建Worker函数,Worker原型对象继承Person的原型对象 Worker.prototype = Person.prototype;并在Worker原型对象上覆盖Person的原型对象上的show

函数。

那么,创建Worker的实例对象p2,在调用函数showName()时会在实例本身进行查找,若没有找到,再沿着__proto__这条链查找上一级原型对象,一层一层向上找(原型链顶端Object.prototype),直到找到为止。

如果当找到__proto__属性为null时,返回 undefined,证明不存在此方法或属性。这样一层一层查找实例上的原型上的属性就构成一条原型链。

好了就到这里了,有不对的地方请指正~~~~

时间: 2024-10-08 18:37:30

JavaScript原型与原型链学习笔记的相关文章

GNU工具链学习笔记

GNU工具链学习笔记 1..so为动态链接库,.a为静态连接库.他们在Linux下按照ELF格式存储.ELF有四种文件类型.可重定位文件(Relocatable file,*.o,*.a),包含代码和数据,可用来连接成可执行文件或共享目标文件;可执行文件(Executable File),ELF可执行文件:共享目标文件(Shared Object File,*.so),包含代码和数据:核心转储文件(Core Dump File),进程意外终止时,系统将该进程的地址空间内容和其他信息保存到该文件中

《javascript DOM 编程艺术》学习笔记(一)

书籍已经看完了前六章的内容,有了一定的编程基础后觉得本书内容相对来说过于简单,应该是完全针对于初学者的(或者如作者所说是写个Web设计师的),作者在表述一个问题,一句代码都解释得非常啰嗦与重复,不过从书中学习到更多的,也是作者想让读者体会的是让大家理解DOM脚本编程技术背后的思路和原则,作者特别以早期Javascript的滥用来强调Web的规范与标准,这一点是非常值得学习的,也是一个程序员的基本素养. 截止到第六章,将所学到的知识点归纳如下: 1.基本语法:与php一样是弱类型语言,虽然功能强大

原型模式——HeadFirst设计模式学习笔记

原型模式:通过复制一个已经存在的实例来返回新的实例,而不是新建实例.被复制的实例就是我们所称的原型,这个原型是可定制的(clone) 特点: 向用户隐藏了创建新实例的复杂性 让用户可以产生未知类型的对象,即只需知道对象实现了哪些接口,而无需知道具体是哪种实现 在某些情况下,复制对象比创建对象更高效 Prototype类需要具备以下两个条件: 实现Cloneable接口.在java语言有一个Cloneable接口,它的作用只有一个,就是在运行时通知虚拟机可以安全地在实现了此接口的类上使用clone

JavaScript闭包(Closure)学习笔记

闭包(closure)是JavaScript语言的一个难点,也是它的特色,很多高级应用都要依靠闭包实现. 下面就是我的学习笔记,对于JavaScript初学者应该是很有用的. 一.变量的作用域 要理解闭包,首先必须理解JavaScript特殊的变量作用域. 变量的作用域无非就是两种:全局变量和局部变量. JavaScript语言的特殊之处,就在于函数内部可以直接读取全局变量. var n=999; function f1() { alert(n); } f1(); // 999 另一方面,在函数

JavaScript作用域(链)学习笔记

作用域是javascript老生常谈的问题,在面试题中也经常出现.此文记录本人对js作用域的理解.从以下三个方面深入探讨js作用域和js作用域链. 1.什么是作用域? 2.什么是作用域链? 3.常见面试题. 一.什么是作用域? 熟悉编程的人都接触过作用域,比如全局变量和局部变量之分.作用域是变量和函数可以访问的范围,即作用域控制着变量和函数的可见性和生命周期. var name = "Aralic"; function person () { //局部变量 var age = &quo

JavaScript权威设计--JavaScript表达式与运算符(简要学习笔记五)

1.3种原始表达式 1.直接量:    1.23    //数字直接量 “hello”    //字符串直接量 ... 2.保留字构成的原始表达式: true    //返回布尔值:真 false    //假 null    //返回一个值:空 3.变量: i    //返回变量i的值 sum    //返回sum的值 2.对象初始化表达式 var p={ x:2.3, y:-1.2 } //一个拥有两个属性成员的对象 对象直接量也可以嵌套: var rea={ upp:{ x:2, y:2

JavaScript设计模式之观察者模式(学习笔记)

设计模式(Design Pattern)对于软件开发来说其重要性不言而喻,代码可复用.可维护.可扩展一直都是软件工程中的追求!对于我一个学javascript的人来说,理解设计模式似乎有些困难,对仅切图.做少量交互效果的FE甚至可能不会用到,但是当你开始使用Angular/Backbone等框架的时候,就无法避免设计模式.MVC/MVVM这些东西了(反正我是伤脑筋). 我学设计模式是刚开始接触编程大概三个月的时候,看一本书<大话设计模式>,里面用C#语言来写,我很无语,因为强类型的编程语言对于

过滤器链-学习笔记

a)一个Web应用可以有0个或多个Filter,多个Filter的组合就是过滤器链b)多个Filter的执行先后顺序,与web.xml文件中配置的顺序有关c)chain.doFilter(request,response)具有二义性: >如果有下一个Filter时,将请求转发给下一个Filter>如果无下一个Filter时,将请求转发给Web资源(serlvet/jsp/html)d)可以将web资源中的一些公共代码,提取出来,放入Filter中 `<filter> <fil

javascript模板引擎之artTemplate 学习笔记

<div id="content"></div><div id="content1"></div><h1>在javascript中存放模板</h1><div id="content2"></div><div id="content3"></div><h1>辅助方法</h1><di