JavaScript的原型与对象

浅谈JavaScript的OOP

OOP的英文全称为Object-oriented programming,也就是我们所说的面向对象程序设计,是一种具有对象概念的程序编程范性,一般而言,面向对象编程与面向过程编程(Procedural programming)相对,具有继承、封装和多态的特性,目前,应用广泛的面向对象语言包括Java、Python、C++、Objective-C、Swift、C#、Ruby和PHP等。
而JavaScript的面向对象思想来自于Self语言,它隶属于OOP的一个子系统,被称为基于原型的编程或者原型程序设计,在JavaScript中,类是不实时的,而是行为重用,是通过已经存在的原型对象的过程实现的,这也被称为面向原型,或者基于实例的编程

栗子:

1
2
3
4
5
6
7
8
9
10
function Person(name,age){
this.name = name;
this.age = age;
this.getInfo = function(){
console.log("我的名字是" + this.name + "今年" + age + "岁")
};
} // 通过这样的方式创建一个Person的原型
// 这时通过new的方式就可以创建一个新的实例
var jack = new Person("jack",25);
// 通过这样的方式,得到一个新的Person实例jack。

目前,ECMAScript 6中新增了”class”作为原型架构之上的语法糖,提供建构对象和处理继承时的另一种语法。

JavaScript中的prototype和proto

prototype是函数对象的一个属性,它的值就是prototype对象,所有实例对象需要共享的属性和方法,都会被放在这个对象里面,那些不需要共享的属性和方法,就会被放在构造函数里面,当实例被创建的时候,就会自动引用prototype对象的水性和方法。————拓展
__proto__是对象的一个内部隐藏属性,他的值是该的原型对象。

对这两个内容的相互对象关系在控制台做一个测试,达到如下结果:
test

通过以上的测试结果,我们可以看出,__proto__作为一个对象内部的属性,它是指向创建它的函数的prototype对象的,它们之间存在着一一对应的关系,当创建一个新的对象时(在JavaScript中,万物皆对象),就会创建一个隐式的__proto__属性,这个属性指向创建它的函数内的prototype属性,这时就可以使用其中的所有值,这也就是我们在创建一个任意类型的对象时,创建出来的对象可以调用很多我们没有手动创建过的方法,譬如toLocalStringtoString等方法。

原型图

将上面的栗子拿到这里,稍作修改:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name,age){
this.name = name;
this.age = age;
this.getInfo = function(){
console.log("我的名字是" + this.name + "今年" + age + "岁")
};
} // 通过这样的方式创建一个Person的原型
Person.prototype.describle = function(){
console.log(this.name + "是" + this.age + "年前出生的");
}
// 这时通过new的方式就可以创建实例
var jack = new Person("jack",25);
var lucy = new Person("lucy",24);

将以上代码做一分析,形成以下原型图

原型图

从上图中,我们可以看到,每一个Person对象被创建之后,他拥有Person中所定义的所有私有变量,并有一个__proto__属性指向prototype中原有的和现定义的所有方法,同时,prototype自身也是一个对象,它也拥有一个__proto__并指向Object的prototype属性,这样一一对应的关系就形成了其中的原型链。

探索

在以下代码中,定义了4个age,它们分别指向的内容是不相同的

1
2
3
4
5
6
7
function People (){
var age = 1 // 使用var定义的age是函数内的一个局部变量
this.age = 10; // 通过this定义的,是函数内的一个私有变量,在创建People的实例时,它将称为其中的一个属性
}
People.age = 20; // People函数的一个私有变量,它与函数内部的内容无关
People.prototype.age = 30; // 在原型内创建的一个age,它在__proto__里创建了一个age属性,对应的值为30