面向对象的言语有一个标志,即具有类的观点,笼统实例对象的大众属性与要领,基于类能够建立恣意多个实例对象,平常具有封装、继续、多态的特征!
但JS中对象与纯面向对象言语中的对象是差别的,ECMA规范定义JS中对象:无序属性的鸠合,其属性能够包括基本值、对象或许函数。
能够简朴理解为JS的对象是一组无序的值,个中的属性或要领都有一个名字,依据这个名字能够接见相映照的值(值能够是基本值/对象/要领)。
一、工场形式
建立对象交给一个工场要领来完成,能够通报参数,但重要瑕玷是没法辨认对象范例,由于建立对象都是运用Object的原生组织函数来完成的。
function createPerson(name, age, job) {
var o = new Object();
o.name = name;
o.age = age;
o.job = job;
o.getName = function () {
return this.name;
}
return o; // 运用return返回天生的对象实例
}
var person = createPerson('Jack', 19, 'SoftWare Engineer');
二、组织函数形式
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = function () {
return this.name;
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engineer');
var person2 = new Person('Liye', 23, 'Mechanical Engineer');
组织函数形式与工场要领区分在于:
没有显式地建立对象
直接将属性和要领赋值给this对象
没有return语句
上述由Person组织函数天生的两个对象person1与person2都是Person的实例,因而能够运用instanceof推断,而且由于一切对象都继续Object,因而person1 instanceof Object也返回真:
console.log(person1 instanceof Person); // true;
console.log(person2 instanceof Person); // true;
console.log(person1 instanceof Object); // true;
console.log(person2 instanceof Object); // true;
console.log(person1.constructor === person2.constructor); // ture;
虽然组织函数体式格局比较不错,但也存在瑕玷,那就是在建立对象时,迥殊针对对象的属性指向函数时,会反复的建立函数实例,以上述代码为基本,能够改写为:
function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = getName;
}
function getName() {
return this.name;
}
三、原型形式
JS中每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,它是一切经由历程new操作符运用函数建立的实例的原型对象。
原型对象最大特点是,一切对象实例同享它所包括的属性和要领,也就是说,一切在原型对象中建立的属性或要领都直接被一切对象实例同享。
function Person() {}
Person.prototype.name = "Jack";
Person.prototype.age = 29;
Person.prototype.getName = function () {
return this.name;
}
var person1 = new Person();
var person2 = new Person();
console.log(person1.getName === person2.getName); // ture;
四、组合组织函数及原型形式
现在最为经常使用的定义范例体式格局,是组合组织函数形式与原型形式。
组织函数形式用于定义实例的属性,而原型形式用于定义要领和同享的属性。
如许,每一个实例都邑有本身的一份实例属性的副本,但同时又同享着对方要领的援用,最大限制的勤俭内存。另外,组合形式还支撑向组织函数通报参数,可谓是集两家之所长。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
Person.prototype = {
constructor: Person, // 原型字面量体式格局会将对象的constructor变成Object,须要强迫指回Person
getName: function () {
return this.name;
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
console.log(person1.lessons); // ["Math", "Physics", "Biology"]
console.log(person2.lessons); // ["Math", "Physics"]
console.log(person1.getName === person2.getName); // true
五、动态原型形式
组合形式中实例属性与同享要领(由原型定义)是星散的,这与纯面向对象言语不太一致。
动态原型形式将一切组织信息都封装在组织函数中,同时又坚持了组合的长处。
其道理就是经由历程推断组织函数的原型中是不是已定义了同享的要领或属性,假如没有则定义,不然不再实行定义历程。
该体式格局只定义一次原型上要领或属性,且将一切组织历程都封装在组织函数中,对原型所做的修正能马上表现一切实例中:
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName) {
Person.prototype = {
constructor: Person, // 原型字面量体式格局会将对象的constructor变成Object,须要强迫指回Person
getName: function () {
return this.name;
}
}
}
var person1 = new Person('Jack', 19, 'SoftWare Engneer');
person1.lessons.push('Biology');
var person2 = new Person('Lily', 39, 'Mechanical Engneer');
console.log(person1.lessons); // ["Math", "Physics", "Biology"]
console.log(person2.lessons); // ["Math", "Physics"]
console.log(person1.getName === person2.getName); // true