您的位置:首页 > Web前端 > JavaScript

javascript对象,函数,原型链

2016-07-18 02:20 323 查看
1.关于对象

javascript无疑是将面向对象思想演绎到一定高度的语言,因为其所能看到的一切皆为对象。数字是对象,字符串是对象,连函数都是对象。对象们拥有相应的属性和方法,若将方法看作是具有功能的属性,那么javascript对象诚然名为属性的容器便无可挑剔。由于属性还支持对象的嵌套,将javascript对象的数据结构在脑中进行推演,不难浮现出一个树形结构。

但静心细看,javascript的对象又有明显不同的两类:原型对象,函数对象。

原型对象,对于以C++,Java等基于类的面向对象语言为基础的同行来说,可能有些很难望文生义。其实这就是对象字面量,即“名/值”对,特别的是此处的“值”就是属性值而非方法。

函数对象,则多是由函数字创建后赋值给标识符的形式。如下源码简单认识:
// 原型对象
var obj = {
"first-name": "Jerome",
"last-name": "Howard"
};
// 函数对象
var add = function (a,b){
return a+b;
};


函数对象中可以嵌套函数,参数可以传递函数,返回值也可以返回函数。

 2.函数调用,继承

在讲javascript的原型继承之前,我觉得先进一步理清函数对象的调用方式是必要的。

函数调用在执行函数体内,有两个很重要的参数:this(指向对象)和arguments(实际参数列表)。而函数调用有四种模式,不同模式下this的指向会有不同。

2.1 方法调用
函数作为一个对象的属性方法被调用时,this绑定到该对象,绑定发生在调用时(延迟绑定)。

2.2 函数调用
函数不作为对象的属性方法而被调用时,this绑定到全局变量。特别是作为内部函数被调用时,若想访问外部函数可重新声明暂存变量。

2.3* 构造器调用
函数创建后以加new前缀的形式来调用。(此方式拙略,javascript对其原型本质缺乏信心,而迎合基于类的语言的对象构造方式)
// 构造器函数创建
var Quo = function(str){
this.status = str;
}
// 构造器函数调用
var myQuo = new Quo("confused");


此调用方式虽然拙略,但其确实提供了一个理解从类继承到原型继承的角度。以基于类的语言角度来看,函数被看做是只具有构造函数的类,可通过new前缀关键字来创建该“类”的对象,但每个这种函数的“类”都具有一个唯一的原型对象。原型对象之于其他由该函数通过构造器调用模式创建出来的对象,关系可以类比嫡长子和庶子的关系。原型对象承担继承的责任,而javascript描绘继承的族谱就是“原型链”。

此处本来是介绍函数调用的,但讲这些,完全是觉得从构造器调用方式的角度,可以很好的理解原型继承和原型链。

以javascript的角度来说,每个函数的原型对象都由其prototype属性指定(原型对象),而每一个对象都具有的__proto__属性,其会指向创建该对象的函数的原型对象(不言而喻,函数对象也是有函数创建的)。那么由函数创建对象的形式所实现的继承关系,便可得到如下关系图谱。



看了这幅图聪明的你,肯定已经发现了我以上描述中的一个纰漏:原型对象的__proto__属性难不成会指向其自身?当然不会这样。先说结果:原型对象的__proto__属性会指向Object.prototype。如何理解呢,如果说以类为基础的面向对象语言的继承是“单性繁殖”,那么javascript的原型继承可以更为恰当地描述为“两性繁殖”。函数直接创建的对象好比“母生子”,父亲是谁呢?对象!(请记住javascript里,一切皆对象)——那个创建原型对象的函数Object()。

2.4 apply调用
一种函数的调用方式,函数对象自带一个apply方法,其接受两个参数,第一个参数指定this指针,第二个参数为传递的参数数组。
// apply调用
var statusObj = {
status: "miaomiao"
}
Quo.prototype.getStatus = function(){
return this.status;
}
var status = Quo.prototype.getStatus.apply(statusObj);
// status : "miaomiao"


3.关于原型链

原型对象和函数对象更深层次的不同,则源于javascript实现继承方式时与传统面向对象语言的差异,这也就造成了许多对于我们学过其他传统面向对象语言的人来说的不习惯。我所说的“传统”的描述并不含有表达javascript作为面向对象语言很先进的意思。像C++、Python、Java都是通过“类”来实现继承的,无论是Java的单继承,还是C++、Python的多继承,其都是明确区分类和对象的——实现体和实现其的模板是有明显不同,而javascript基于的原型继承,就没有类的概念,而他所说的对象与C++,Java中的“对象”则也是两个完全不同的概念。

通过2.3的叙述,原型链的介绍会容易许多,先说原型链的作用:我获取对象的某一属性时,如果该对象中没有所需的属性,则自动会去其__proto__对象的属性中继续寻找,如若还未寻得,则继续搜寻__proto__对象的__proto__对象的属性,直至寻得或返回根本没找到。这种由__proto__属性链接起来的一串对象就称为原型链。

另外,在循环一个对象的属性时,会通过hasOwnProperty方法来确定这个属性是该对象的成员还是来自于原型链的。
// 原型链-属性查找
for(myVal in obj){
if (obj.hasOwnProperty(myVal)) {
...
}
}


自己的见闻周更

有兴趣的朋友感谢关注下捧捧场

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息