文章目录
JavaScript 与面向对象
JavaScript是直译式脚本语言、弱类型,基于原型的语言。
在JavaScript中虽然没有类的概念,但却是面向对象的开发语言。既然是面向对象,JavaScript是如何做到面向对象的继承的呢?答案就是prototype。
JavaScript使用最多的就是函数,但JavaScript的函数和一般面向过程编程语言(比如C)和面向对象的开发语言( 比如Java不同),其使用函数创建对象,函数本身也是对象。
JavaScript 函数
函数一般用来定义一段逻辑代码,以下是比较习惯的定义与调用方式
function myFunc(){
alert("Hello");
}
myFunc();
但是在JavaScript中,也可以这样定义:
var myFunc = function(){
alert("Hello");
};
myFunc();
JavaScript 构造函数与对象
以上用法,看不出对象的概念。但是,如果是如下定义的话,
function MyClass(name){
this.name = name;
}
var myClassInstance = new MyClass("Oscar");
这样看起来就与类和实例的概念很类似了,MyClass前面的function相当于类定义的关键字。对以上代码说明如下:
- this对象指向生成的对象实例
- 使用new操作符,初始化对象实例。
在Chrome的调试模式下的效果如下:
这个对象除了自定义的name属性之外,还有一个__proto__的属性。这个属性很关键,JavaScript就是使用它实现面向对象的继承等特性。
注意:
此处基于Chrome浏览器,__proto__前后都是两个下划线。ES标准定义的属性是[[Prototype]]。
函数与对象,prototype属性与__proto__属性
在JavaScript中,函数也是对象,所以也拥有__proto__属性,除此函数还包含了prototype属性(原型属性)。以上面的MyClass函数为例,数据结构如下:
函数是一种对象,对象由函数创建,两者看起来是蛋和鸡的关系。
prototype和__proto__的关系是: 函数的prototype属性值与该函数创建的对象的__proto__属性值是相同的,以上面定义的类为例:
myClassInstance.proto===MyClass.prototype
函数的prototype作用-动态添加属性和方法
JavaScript与Java语言有一个较大差异: 对象的属性不强制要求在类(构造函数)中定义,而是可以在对象实例中添加,以上面的MyClass构造函数为例:
var myClassInstance = new MyClass(“Oscar”);
增加一个年龄的的属性age和值,只需要如下代码即可:
myClassInstance.age = 18;
这样的好处是灵活,不需要修改构造函数,但是如果要增加一个有默认值的属性,比如国家(country),默认值都是China,如果有很多MyClass的实例,就需要每个实例对象单独修改,通过prototype属性就可以实现该效果了。代码如下:
MyClass.prototype.country = “China”;
当然,这里也可以修改构造函数实现,类似:
function MyClass(name){
this.name = name;
this.country = “China”;
}
但是如果使用的是第三方库,而且有的第三方库对类进行了多层级封装,有的甚至进行了压缩,就无法修改构造函数了。
原型(prototype)属性的作用相当于父类。