JavaScript学习总结(五)原型和原型链详解
来源:互联网 发布:js点击弹出对话框 编辑:程序博客网 时间:2024/06/06 05:45
私有变量和函数
在函数内部定义的变量和函数,如果不对外提供接口,外部是无法访问到的,也就是该函数的私有的变量和函数。
<script type="text/javascript"> function Box(){ var color = "blue";//私有变量 var fn = function() //私有函数 { } }</script>
这样在函数对象Box
外部无法访问变量color
和fn
,他们就变成私有的了:
var obj = new Box(); alert(obj.color);//弹出 undefined alert(obj.fn);//同上
静态变量和函数
当定义一个函数后通过点号 “.”
为其添加的属性和函数,通过对象本身仍然可以访问得到,但是其实例却访问不到,这样的变量和函数分别被称为静态变量
和静态函数
。
<script type="text/javascript"> function Obj(){}; Obj.num = 72;//静态变量 Obj.fn = function() //静态函数 { } alert(Obj.num);//72 alert(typeof Obj.fn)//function var t = new Obj(); alert(t.name);//undefined alert(typeof t.fn);//undefined</script>
实例变量和函数
在面向对象编程中除了一些库函数我们还是希望在对象定义的时候同时定义一些属性和方法,实例化后可以访问,js
也能做到这样
<script type="text/javascript"> function Box(){ this.a=[]; //实例变量 this.fn=function(){ //实例方法 } } console.log(typeof Box.a); //undefined console.log(typeof Box.fn); //undefined var box=new Box(); console.log(typeof box.a); //object console.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); //object var box2=new Box(); console.log(box2.a); //[] console.log(typeof box2.fn); //function</script>
在box1
中修改了a
和fn
,而在box2
中没有改变,由于数组和函数都是对象,是引用类型,这就说明box1
中的属性和方法与box2
中的属性与方法虽然同名但却不是一个引用,而是对Box
对象定义的属性和方法的一个复制。
这个对属性来说没有什么问题,但是对于方法来说问题就很大了,因为方法都是在做完全一样的功能,但是却又两份复制,如果一个函数对象有上千和实例方法,那么它的每个实例都要保持一份上千个方法的复制,这显然是不科学的,这可肿么办呢,prototype
应运而生。
基本概念
我们创建的每个函数都有一个prototype
属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含可以由特定类型的所有实例共享的属性和方法。那么,prototype
就是通过调用构造函数而创建的那个对象实例的原型对象。
使用原型的好处是可以让对象实例共享它所包含的属性和方法。也就是说,不必在构造函数中添加定义对象信息,而是可以直接将这些信息添加到原型中。使用构造函数的主要问题就是每个方法都要在每个实例中创建一遍。
在JavaScript
中,一共有两种类型的值,原始值和对象值。每个对象都有一个内部属性 prototype
,我们通常称之为原型。原型的值可以是一个对象,也可以是null
。如果它的值是一个对象,则这个对象也一定有自己的原型。这样就形成了一条线性的链,我们称之为原型链
。
含义
函数可以用来作为构造函数来使用。另外只有函数才有prototype属性并且可以访问到,但是对象实例不具有该属性,只有一个内部的不可访问的__proto__
属性。__proto__
是对象中一个指向相关原型的神秘链接。按照标准,__proto__
是不对外公开的,也就是说是个私有属性,但是Firefox的引擎将他暴露了出来成为了一个共有的属性,我们可以对外访问和设置。
<script type="text/javascript"> var Browser = function(){}; Browser.prototype.run = function(){ alert("I'm Gecko,a kernel of firefox"); } var Bro = new Browser(); Bro.run();</script>
当我们调用Bro.run()
方法时,由于Bro
中没有这个方法,所以,他就会去他的__proto__
中去找,也就是Browser.prototype
,所以最终执行了该run()方法。(在这里,函数首字母大写的都代表构造函数,以用来区分普通函数)
当调用构造函数创建一个实例的时候,实例内部将包含一个内部指针(__proto__
)指向构造函数的prototype
,这个连接存在于实例和构造函数的prototype
之间,而不是实例与构造函数之间。
<script type="text/javascript">function Person(name){ //构造函数 this.name=name; } Person.prototype.printName=function() //原型对象 { alert(this.name); } var person1=new Person('Byron');//实例化对象 console.log(person1.__proto__);//Person console.log(person1.constructor);//自己试试看会是什么吧 console.log(Person.prototype);//指向原型对象Person var person2=new Person('Frank');</script>
Person
的实例person1中包含了name属性,同时自动生成一个__proto__
属性,该属性指向Person的prototype,可以访问到prototype
内定义的printName
方法,大概就是这个样子的:
每个JavaScript
函数都有prototype
属性,这个属性引用了一个对象,这个对象就是原型对象。原型对象初始化的时候是空的,我们可以在里面自定义任何属性和方法,这些方法和属性都将被该构造函数所创建的对象继承。
那么,现在问题来了。构造函数、实例和原型对象三者之间有什么关系呢?
实例就是通过构造函数创建的。实例一创造出来就具有constructor
属性(指向构造函数)和__proto__
属性(指向原型对象),
构造函数中有一个prototype
属性,这个属性是一个指针,指向它的原型对象。
原型对象内部也有一个指针(constructor
属性)指向构造函数:Person.prototype.constructor = Person;
实例可以访问原型对象上定义的属性和方法。
在这里person1和person2就是实例,prototype
是他们的原型对象。
再举个栗子:
<script type="text/javascript"> function Animal(name) //积累构造函数 { this.name = name;//设置对象属性 } Animal.prototype.behavior = function() //给基类构造函数的prototype添加behavior方法 { alert("this is a "+this.name); } var Dog = new Animal("dog");//创建Dog对象 var Cat = new Animal("cat");//创建Cat对象 Dog.behavior();//通过Dog对象直接调用behavior方法 Cat.behavior();//output "this is a cat" alert(Dog.behavior==Cat.behavior);//output true;</script>
可以从程序运行结果看出,构造函数的prototype
上定义的方法确实可以通过对象直接调用到,而且代码是共享的。(可以试一下将Animal.prototype.behavior
中的prototype
属性去掉,看看还能不能运行。)在这里,prototype属性指向Animal对象。
- JavaScript学习总结(五)原型和原型链详解
- JavaScript学习总结(五)原型和原型链详解
- javascript学习笔记(五)原型和原型链详解
- JavaScript学习总结(五)原型和原型链详解(续)
- JavaScript学习--Item15 prototype原型和原型链详解
- JavaScript原型与原型链学习总结
- JavaScript prototype原型和原型链详解
- JavaScript-- prototype原型和原型链详解
- JavaScript中原型和原型链详解
- JavaScript原型和原型链详解
- JavaScript中原型和原型链详解
- javascript笔记--原型和原型链详解
- javascript原型和原型链
- Javascript原型和原型链
- JavaScript原型和原型链
- Javascript原型和原型链
- Javascript原型和原型链
- JavaScript原型和原型链
- (3) 百度2011研发工程师笔试卷
- [3.2.0]JVM调优原理以及降低Cache操作的内存占比
- “Ubuntu 环境下npm使用时报错 node: not found 的处理方法”
- 关于ARGB_8888、ALPHA_8、ARGB_4444、RGB_565的理解
- springmvc 启动错误java.lang.IllegalArgumentException
- JavaScript学习总结(五)原型和原型链详解
- Android利用ViewPager+GridView,实现网格布局(功能列表)并能水平滑动
- matlab-基础 plot输出的图像的线变粗
- hbase 增删改查基本操作
- leetcode 87 Scramble String(递归+剪枝)
- linux mint上安装vim spf13
- matlab-基础 给plot输出的图像加上x,y轴的标签
- CSS vertical-align属性的用法
- 裸机开发之点亮LED