OOP
面向对象编程(Object Oriented Programming ,简称OOP)是目前主流的编程范式。它将真实世界各种复杂的关系,抽象为一个个对象,然后由对象之间的分工与合作,完成对真实世界的模拟。 每一个对象都是功能中心,具有明确分工,可以完成接受信息、处理数据、发出信息等任务。对象可以复用,通过继承机制还可以定制。因此,面向对象编程具有灵活、代码可复用、高度模块化等特点,容易维护和开发,比起由一系列函数或指令组成的传统的过程式编程(procedural programming),更适合多人合作的大型软件项目。
对象
对象(object)理解为是对单个物体的抽象,当实物被抽象为对象,实物与实物之间的关系就变成了对象与对象之间的关系,从而就可以模拟现实情况,针对对象进行编程。对象是一个容器,里面封装了属性(property)与方法(method),属性是对象的状态,方法是对象的行为。
构造函数
面向对象编程的第一步,就是要生成对象。 前面说过,对象是单个实物的抽象。通常需要一个模板,表示某一类实物的共同特征,然后对象根据这个模板生成。在JavaScript语言的对象体系中,对象的模板是基于构造函数和原型链。JavaScript 语言使用构造函数(constructor)作为对象的模板。所谓"构造函数",就是专门用来生成实例对象的函数。它就是对象的模板,描述实例对象的基本结构。一个构造函数,可以生成多个实例对象,这些实例对象都有相同的结构。构造函数就是一个普通的函数,但具有自己的特征和用法。
例:
var Vehicle = function () {
this.price = 1000;
};
上面代码中,Vehicle
就是构造函数。为了与普通函数区别,构造函数名字的第一个字母通常大写。构造函数还有两个特点:
- 函数体内部使用了this关键字,代表了索要生成的对象实例
- 生成对象的时候必须使用new命令
new命令
基本用法:new命令的作用,就是执行构造函数,返回一个实例对象。
原理
使用new
命令时,它后面的函数依次执行下面的步骤。
-
创建一个空对象,作为将要返回的对象实例。
-
将这个空对象的原型,指向构造函数的
prototype
属性。 -
将这个空对象赋值给函数内部的
this
关键字。 -
开始执行构造函数内部的代码。
也就是说,构造函数内部,this
指的是一个新生成的空对象,所有针对this
的操作,都会发生在这个空对象上。构造函数之所以叫"构造函数",就是说这个函数的目的,就是操作一个空对象(即this
对象),将其"构造"为需要的样子。如果构造函数内部有return
语句,而且return
后面跟着一个对象,new
命令会返回return
语句指定的对象;否则,就会不管return
语句,返回this
对象。
Object对象的相关方法
JavaScript 在Object对象上面,提供了很多相关方法,处理面向对象编程的相关操作。下面介绍部分方法:
Object.getPrototypeOf()
Object.getPrototypeOf方法返回参数对象的原型。这是获取原型对象的标准方法。
var F = function () {};
var f = new F();
Object.getPrototypeOf(f) === F.prototype // true
上面代码中,实例对象f的原型是F.prototype
下面是几种特殊对象的原型
// 空对象的原型是 Object.prototype
Object.getPrototypeOf({}) === Object.prototype // true
// Object.prototype 的原型是 null
Object.getPrototypeOf(Object.prototype) === null // true
// 函数的原型是 Function.prototype
function f() {}
Object.getPrototypeOf(f) === Function.prototype // true
Objecct.create()
JavaScript 提供了Objecct.create()方法,用来满足这种需求。该方法接受一个对象作为参数,然后以它为原型,返回一个实例对象。该实例完全继承原型对象的属性。
// 原型对象
var A = {
print: function () {
console.log('hello');
}
};
// 实例对象
var B = Object.create(A);
Object.getPrototypeOf(B) === A // true
B.print() // hello
B.print === A.print // true
上面代码中,Objecct.create()方法以A
对象为原型,生成了B
对象。B
继承了A
的所有属性和方法。
原型链
JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个"原型链"(prototype chain):对象到原型,再到原型的原型......
例如:a--->b--->c--->d--->......--->Object
如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。而Object.prototype的原型是null,null没有任何的属性和方法,也没有自己的原型。因此原型链的尽头就是null.
this关键字
this关键字是一个非常重要的语法点。毫不夸张地说,不理解它的含义,大部分开发任务都无法完成。this可以用在构造函数之中,表示实例对象。除此之外,this还可以用在别的场合。但不管是什么场合,this都是返回一个对象。简单说this就是属性或方法"当前"所在的对象。
例如:
var person = {
name: '张三',
describe: function () {
return '姓名:'+ this.name;
}
};
person.describe()
// "姓名:张三"
上面代码中,this.name表示name属性所在的那个对象。由于this.name是在describe方法中调用,而describe方法所在的当前对象是person,因此this指向person,this.name就是person.name.
总结一下,在JavaScript语言中,一切皆对象,运行环境也是对象,所以函数都是在某个对象中运行,this就是函数运行时所在的对象(环境),但在JavaScript支持运行环境动态切换,也就是说,this的指向是的动态的,没办法事先确定指向哪个对象。