岂知道js的面向对象编程

面向对象的言语来一个标明,即拥有类的定义,抽象实例对象的公性质和法,基于类可创造任意多独实例对象,一般装有封装、继承、多态的特征!但JS中目标同纯面向对象语言中的对象是见仁见智之,ECMA标准定义JS中目标:无序属性的成团,其性质可以分包基本值、对象或函数。可以简简单单明了啊JS的对象是平等组无序的价,其中的特性或方式都来一个名字,根据这个名字可以看相映射的价值(值好是基本值/对象/方法)。

合法说

原型模式如类模式一样,都是凡一致种植编程泛型,即编程的方法论。另外近年来大红大紫的函数编程也是如出一辙种植编程泛型。JavaScript的父Brendan
Eich在计划JavaScript时,从平开始就是从不打算啊其在类的概念,而是借鉴了另外两派基于原型的之语言:Self和Smalltalk。

  既然跟也面向对象语言,那就算得有创建对象的方。在类似语言中,对象基于模板来创造,首先定义一个接近作为针对切实世界之泛,然后由接近来实例化对象;而于原型语言中,对象为克隆另一个目标的法子开创,被克隆的母体称为原型对象。

平等、理解对象:

第一种:基于Object对象

图片 1

var person = new Object();
person.name = 'My Name';
person.age = 18;
person.getName = function(){
return this.name;
}

图片 2

老二种植:对象字面量方式(比较清楚的找对象涵盖的特性和智)

图片 3

var person = {
    name : 'My name',
    age : 18,
    getName : function(){
        return this.name;
    }
}

图片 4

JS的靶子好行使‘.’操作符动态的恢宏其性能,可以用’delete’操作符或将属于性值设置也’undefined’来删除属性。如下:

person.newAtt=’new Attr’;//添加属性
alert(person.newAtt);//new Attr
delete person.age;
alert(person.age);//undefined(删除属性后值为undefined);

老二、对象属性类型

ECMA-262第5本子定义了JS对象属性中特征(用于JS引擎,外部无法直接访问)。ECMAScript中起些许栽特性:数据性与看器属性

1、数据性:

多少性指包含一个数据值的职位,可于拖欠位置读取或写入值,该属性有4单供述其一言一行之特点:

[[configurable]]:表示是否以delete操作符删除从而再次定义,或是否修改为访器属性。默认为true;

[[Enumberable]]:表示是否只是经for-in循环返回属性。默认true;

[[Writable]]:表示是否可改属性的价。默认true;

[[Value]]:包含该属性之数据值。读取/写副且是该值。默认为undefined;如上面实例对象person中定义了name属性,其值为’My
name’,对该值的改动都反正在这岗位

倘改对象属性的默认特征(默认都也true),可调用Object.defineProperty()方法,它接受三独参数:属性所在对象,属性名和一个叙述吻合对象(必须是:configurable、enumberable、writable和value,可装一个要么多个价)。

一般来说:(浏览器支持:IE9+、Firefox 4+、Chrome、Safari5+)

图片 5

var person = {};
Object.defineProperty(person, 'name', {
configurable: false,
writable: false,
value: 'Jack'
});
alert(person.name);//Jack
delete person.name;
person.name = 'lily';
alert(person.name);//Jack

图片 6

可以看出,delete及重置person.name的价都没有立竿见影,这虽是坐调用defineProperty函数修改了目标属性之风味;值得注意的凡只要以configurable设置也false,则无法还使用defineProperty将那修改也true(执行会报错:can’t
redefine non-configurable property);

2、访问器属性:

她根本概括同对getter和setter函数,在读取访问器属性时,会调用getter返回有效值;写副访问器属性时,调用setter,写副新值;该属性有以下4单性状:

[[Configurable]]:是否可通过delete操作符删除重新定义属性;

[[Numberable]]:是否只是透过for-in循环查找该属性;

[[Get]]:读取属性时调用,默认:undefined;

[[Set]]:写副属性时调用,默认:undefined;

访问器属性不可知一直定义,必须以defineProperty()来定义,如下:

图片 7

var person = {
_age: 18
};
Object.defineProperty(person, 'isAdult', {
get: function () {
if (this._age >= 18) {
return true;
} else {
return false;
}
}
});

图片 8

alert(person.isAdult?’成年’:’未成年’);//成年
从者会,定义访问器属性时getter与setter函数不是须的,并且,在概念getter与setter时莫可知指定属性之configurable及writable特性;

另外,ECMA-262(5)还提供了一个Object.defineProperties()方法,可以用来一次性定义多只属性之特性:

图片 9

var person = {};
Object.defineProperties(person,{
_age:{
value:19
},
isAdult:{
get: function () {
if (this._age >= 18) {
return true;
} else {
return false;
}
}
}
});

图片 10

alert(person.isAdult?’成年’:’未成年’);//成年

上述代码用Object.defineProperties()方法而定义了_age及isAudlt两只特性的性状

除此以外,使用Object.getOwnPropertyDescriptor()方法可以取让定属性的特性:

var descriptor = Object.getOwnPropertyDescriptor(person,’_age’);
alert(descriptor.value);//19
于数据性,可以博:configurable,enumberable,writable和value;

对访问器属性,可以取得:configurable,enumberable,get和set

其三、创建对象

采用Object构造函数或对象字面量都可创建对象,但缺点是创办多单对象时,会产生大量底重代码,因此下介绍可缓解之题目的创建对象的法

1、工厂模式

图片 11

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');

图片 12

创建对象交给一个厂方法来贯彻,可以传递参数,但关键症结是无力回天辨识对象类型,因为创建对象都是下Object的原生构造函数来成功的。

2、构造函数模式

图片 13

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');

图片 14

用从定义之构造函数(与一般函数一样,只是用它们来创建对象),定义对象类型(如:Person)的属性与措施。它与工厂方法分别在:

并未显式地创建对象
一直用性与办法赋值给this对象;
没有return语句;
另外,要开创Person的实例,必须动new关键字,以Person函数为构造函数,传递参数就目标创建;实际创造经过以下4只经过:

开创一个目标
将函数的打算域赋给新目标(因此this指为此新对象,如:person1)
履构造函数的代码
返该目标
上述由Person构造函数生成的鲜单对象person1与person2还是Person的实例,因此好采取instanceof判断,并且因为兼具目标还继承Object,因此person1
instanceof Object也回真:

alert(person1 instanceof Person);//true;
alert(person2 instanceof Person);//true;
alert(person1 instanceof Object);//true;
alert(person1.constructor === person2.constructor);//ture;

虽说构造函数方式比不易,但也是欠缺,那就算是当创建对象时,特别对对象的性质指向函数时,会再次的创导函数实例,以上述代码为底蕴,可以改写为:

图片 15

function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = new Function () {//改写后效果与原代码相同,不过是为了方便理解
return this.name;
}
}

图片 16

上述代码,创建多只实例时,会再调用new

Function();创建多独函数实例,这些函数实例还免是一个图域中,当然就貌似不会见来摩擦,但眼看会促成内存浪费。当然,可以在函数中定义一个getName

getName的援,而getName函数在Person外定义,这样可以解决再创建函数实例问题,但于效益及并无打至包的效益,如下所示:

图片 17

function Person(name,age,job){
this.name = name;
this.age = age;
this.job = job;
this.getName = getName;
}
function getName() {//到处是代码,看着乱!!
return this.name;
}

图片 18

3、原型模式

JS每个函数都生一个prototype(原型)属性,这个特性是一个指针,指向一个对象,它是颇具通过new操作符使用函数创建的实例的原型对象。原型对象极其深特点是,所有目标实例共享它所包含的属性和法,也就是说,所有以原型对象中开创的性质或方式都一直叫抱有目标实例共享。

图片 19

function Person(){
}
Person.prototype.name = 'Jack';//使用原型来添加属性
Person.prototype.age = 29;
Person.prototype.getName = function(){
return this.name;
}
var person1 = new Person();
alert(person1.getName());//Jack
var person2 = new Person();
alert(person1.getName === person2.getName);//true;共享一个原型对象的方法

图片 20

原型是靠于原型对象的,这个原型对象与构造函数没有尽怪关系,唯一的涉是函数的prototype是指为这原型对象!而依据构造函数创建的对象实例也带有一个里面指针也:[[prototype]]本着原型对象。

实例属性或艺术的顾过程是相同软搜索过程:

率先从目标实例本身开始,如果找到属性就直接返回该属性值;
假使实例本身不存在而寻找属性,就延续寻找指针指向的原型对象,在里搜给得名字的性,如果有就是赶回;
因以上分析,原型模式创造的靶子实例,其特性是共享原型对象的;但为足以团结实例中再开展定义,在探寻时,就无自原型对象获得,而是根据查找原则,得到本实例的返;简单的话,就是实例中属于性会屏蔽原型对象被之性;

原型与in操作符

同等句话:无论原型中属性,还是对象实例的属性,都好下in操作符访问到;要惦记看清是否是实例本身的习性可以利用object.hasOwnProperty(‘attr’)来判定;

原生对象中原型

原生对象中原型与普通对象的原型一样,可以添加/修改属性或方法,如以下代码为所有字符串对象上加去左右空原型方法:

String.prototype.trim = function(){
return this.replace(/^\s+/,'').replace(/\s+$/,'');
}
var str = ' word space ';
alert('!'+str.trim()+'!');//!word space!

原型模式之弱点,它大概了啊构造函数传递初始化参数,这当必程序带来不方便;另外,最重大是当对象的特性是引用类型时,它的价是未转移的,总是引用和一个表对象,所有实例对该对象的操作都见面其他实例:

图片 21

function Person() {
}
Person.prototype.name = 'Jack';
Person.prototype.lessons = ['Math','Physics'];
var person1 = new Person();
person1.lessons.push('Biology');
var person2 = new Person();
alert(person2.lessons);//Math,Physics,Biology,person1修改影响了person2

图片 22

4、组合构造函数及原型模式

此时此刻极其常用的定义类型方式,是整合构造函数模式和原型模式。构造函数模式用于定义实例的特性,而原型模式用于定义方法和共享的性。结果,每个实例都见面产生协调的一模一样客实例属性的副本,但又还要共享着对方方法的援,最充分限度的省内存。此外,组合模式还支持为构造函数传递参数,可谓是汇两家的所长。

图片 23

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');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法

图片 24

每当所点的JS库中,jQuery列的包装就是行使组合模式来实例的!!!

5、动态原型模式

结合模式受到实例属性与共享方法(由原型定义)是分离之,这与纯粹面向对象语言不极端一致;动态原型模式将有结构信息都封装在构造函数中,又保持了整合的亮点。其规律就是经判断构造函数的原型中是不是业已定义了共享的不二法门还是性质,如果无则定义,否则不再履行定义过程。该办法才原型上方式要性质只定义一不好,且拿拥有结构过程还封闭装在构造函数中,对原型所举行的改动能即时体现所有实例中:

图片 25

function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.lessons = ['Math', 'Physics'];
}
if (typeof this.getName != 'function') {//通过判断实例封装
  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');
alert(person1.lessons);//Math,Physics,Biology
alert(person2.lessons);//Math,Physics
alert(person1.getName === person2.getName);//true,//共享原型中定义方法