JavaScript面向对象学习笔记
-
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。准确地说,这些属性和方法定义在Object的构造器函数(constructor functions)之上的
prototype
属性上,而非对象实例本身。Java通过首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中,在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是__proto__属性,是从构造函数的prototype
属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法,所以JavaScript是基于原型链继承的。 -
JavaScript面向对象中需要注意以下几点:
(1)JavaScript中除了基本类型外其他都可以看做对象,而每个实例对象都有一个_proto_属性,它指向构造这个实例对象的构造函数的prototype属性。
(2)所有的函数对象都拥有一个特殊的属性prototype属性,该属性指向实例对象的原型对象,经常使用原型对象来实现继承。
(3)prototype是一个原型对象,所以它有一个属性_proto_,这个值指向构造出这个原型对象的构造函数的prototype属性。它还有另外一个属性constructor,它指向指向该原型对象对应的构造函数。
-
js中的原型继承:首先我们定义了一个构造函数Person,有
first, last, age, gender, interests等属性,所有的方法都定义在构造器的prototype上,如greeting方法。
function Person(first, last, age, gender, interests) { this.name = { first, last }; this.age = age; this.gender = gender; this.interests = interests; }; Person.prototype.greeting = function() { alert('Hi! I\'m ' + this.name.first + '.'); };
现在我们想要创建一个Teacher类,这个类会继承Person类,同时包括
- 一个新的属性
subject
——这个属性包含了教师教授的学科。 - 一个被更新的
greeting()
方法,这个方法打招呼听起来比一般的greeting()
方法更正式一点——对于一个教授一些学生的老师来说。
这里我们需要用到call()函数。这个函数允许您调用一个在这个文件里别处定义的函数。第一个参数指明了在您运行这个函数时想对“this
”指定的值,也就是说,您可以重新指定您调用的函数里所有“this
”指向的对象。其他的变量指明了所有目标函数运行时接受的参数。
Teacher.prototype.greeting = function() { var prefix; if(this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') { prefix = 'Mr.'; } else if(this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') { prefix = 'Mrs.'; } else { prefix = 'Mx.'; } alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.'); };
之后我们需要让Teacher类继承Person类中的所有方法:
Teacher.prototype = Object.create(Person.prototype);
我们通过Object.create(Person.prototype)实现了Teacher类继承Person类的方法,但是此时Teacher.prototype.constructor指向的是Person方法,这样是有问题的,所以我们还需要:
Teacher.prototype.constructor = Teacher;
这样就将
Teacher.prototype.constructor 指向了 Teacher 方法本身。
现在我们还剩最后一项工作,在构造函数Teacher()
上定义一个新的函数greeting()
。最简单的方法是在Teacher的原型上定义它—把以下代码添加到您代码的底部:
Teacher.prototype.greeting = function() { var prefix; if(this.gender === 'male' || this.gender === 'Male' || this.gender === 'm' || this.gender === 'M') { prefix = 'Mr.'; } else if(this.gender === 'female' || this.gender === 'Female' || this.gender === 'f' || this.gender === 'F') { prefix = 'Mrs.'; } else { prefix = 'Mx.'; } alert('Hello. My name is ' + prefix + ' ' + this.name.last + ', and I teach ' + this.subject + '.'); };