品设计模式之二

品设计模式之二
第二章 面向对象编程
1、封装
* 面向对象编程就是将需求抽象成一个对象,然后针对这个对象分析其特征与动作(属性与方法),这个对象成为类。
* 面向对象编程有个特点:封装。就是把需要的功能放在一个对象里。
* JS创建一个类的方式:首先声明一个函数保存在一个变量里,通常这个代表类的变量名首字母大写。然后在这个函数的内部通过对this变量添加属性或方法来实现对类添加属性或方法。也可以通过在类的原型上添加属性和方法,有两种方式,一种是一一为原型对象属性赋值,另一种是将一个对象赋值给类的原型对象。这样我们将所需的属性和方法都抽象在Person类里了,使用时需要用new关键字来实例化(创建)新的实例对象,通过点语法访问实例对象的属性和方法。
* 通过this添加的属性和方法在prototype上添加的有什么区别?通过this添加的属性和方法是在当前对象上添加的,然而js是一种基于原型ptototype的语言,所以每创建一个对象时,都有一个原型prototype用来指向所继承的属性和方法。通过prototype继承的并不是对象自身的,所以在使用这些方法时,都需要通过ptototype一层层查找。通过this定义的是该对象本身拥有的,所以每次通过类创建一个新对象时,this指向的属性和方法都会得到创建,而通过prototype定义的属性和方法是每个对象通过prototype间接访问到的,所以通过类创建一个新对象时这些属性和方法不会再次创建。
* 由于js的函数级作用域,声明在函数内部的变量和方法在外界无法访问,通过该特性可以创建类的私有属性和私有方法。在函数内部通过this创建的属性和方法,在创建对象时每个对象本身都各自拥有一份并且可以在外部访问到,叫共有属性和特权方法(累的构造器)。
* 通过new关键字创建新对象时,由于类外面通过点语法添加的属性和方法没有执行到,所以新创建的对象中无法获取他们,但可以通过类使用。因此在类外面通过点语法定义的称为类的静态共有属性和静态共有方法。而通过prototype创建的称为共有属性和共有方法。
* 小结:类有三种方式定义属性和方法。一是构造函数内的通过this.name定义,这是供实例化对象复制用的;二是构造函数外的,通过点语法添加的,实例化对象是访问不到的,但是类本身可以访问到;三是类的原型中的,十里湖可以通过原型链简洁的访问到,供所有实例化对象所共用的。

栗子:
白菜1
var Person = function (name, age) {
this.name = name;
this.age = age;
}

白菜2
Person.prototype.getName = function () {}

白菜3
Person.prototype = {
getAge: function () {}
}
var me = new Person(‘xiao’, 18);
console.log(me.age);
me.getName();

2、继承

2、1 子类的原型对象——类式继承
* 类式继承方式:将父类的实例赋值给子类的原型。 Son.prototype = new Parent();
* 类式继承原理:父类的实例对象可以访问父类原型上以及从父类构造函数中复制的属性和方法。将这个实例对象赋值给子类的原型,那么这个子类的原型同样可以访问父类原型上以及父类构造器上的属性和方法。
* 可以通过instanceof来检测某个对象是否是某个类的实例,或者说某个对象是否继承了某个类,这样就可以判吨啊对象与类之间的继承关系了。instanceof是通过对象的prototype链来确定这个对象是否是某个类的实例,并不表示两者的继承。
* 类式继承注意两点。一是,由于子类通过其原型prototype对父类实例化,继承了父类,所以说父类中的共有属性要是引用类型,就会在子类中被所有实例共用,因此一个子类的实例更改子类原型从父类构造函数中继承来的共有属性就会直接影响其他子类。二是,由于子类实现的继承是靠其原型prototype对父类的实例化实现的,因此在创建父类的时候,是无法向父类传递参数的,因而在实例化父类时也无法对父类构造函数内的属性进行初始化。
* 栗子:
function Parent () {
this.names = [‘xiao’, ‘hua’, ‘hong’]
}
function Son () {}
Son.prototype = new Parent();
var son1 = new Son();
var son2 = new Son();
console.log(son1.names); // [‘xiao’, ‘hua’, ‘hong’]
son2.names.push(‘lala’);
console.log(son1.names); // [‘xiao’, ‘hua’, ‘hong’, ‘haha’]

2、2 创建即继承——构造函数继承
* 构造函数式继承是通过在子类的构造函数作用环境中执行一次父类的构造函数来实现的;
栗子:
function Parent (id) {
this.names = [‘xiao’, ‘hua’, ‘hong’];
this.id = id;
}
Parent.prototype.showNames = function () {
console.log(this.names);
}
function Son (id) {
Parent.call(this, id);
}
var son1 = new Son(11);
var son2 = new Son(22);
son1.names.push(’son1’);
console.log(son1.names); // [‘xiao’, ‘hua’, ‘hong’, ’son1’]
console.log(son1.id); // 11
console.log(son2.names); // [‘xiao’, ‘hua’, ‘hong’]
console.log(son2.id); // 22
son1.showNames(); // TypeError
* 上栗子中,构造函数式继承的精髓是Parent.call(this, id);在子类中调用父类时将子类中的变量在父类中执行一遍,由于父类中是给this绑定属性的,因此子类自然也继承了父类的共有属性。由于这种类型的继承没有涉及原型prototype,因此父类的原型方法不会被子类继承,而若想要被子类继承就必须放在构造函数中,这样创建出的每个实例都会单独复制一份,违背了代码复用的原则。
* 为了综合类式继承与构造函数式继承的优点——组合继承

2、3 将优点为我所用——组合继承
* 类式继承是通过子类的原型prototype对父类实例化来实现的;
* 构造函数式继承是通过在子类的构造函数作用环境中执行一次父类的构造函数来实现的;
* 栗子:
function Parent (id) {
this.names = [‘xiao’, ‘hua’, ‘hong’];
this.id = id;
}
Parent.prototype.showNames = function () {
console.log(this.names);
}
function Son (id, age) {
Parent.call(this, id);
this.age = age;
}
Son.prototype = new Parent();
Son.prototype.getAge = function () {
console.lot(this.age);
}
var son1 = new Son(‘id1’, 18);
son1.names.push(’son1’);
son1.names // [‘xiao’, ‘hua’, ‘hong’, ’son1’]
son1.getAge(); // 18
var son2 = new Son(‘id2’, 24);
son2.names //[‘xiao’, ‘hua’, ‘hong’]

  • 组合继承 = 在子类构造函数中执行父类构造函数 + 在子类原型上实例化父类;这样就融合优点去除缺点。
  • 优点:子类的实例中更改父类继承下来的引用类型属性,不会影响到其他实例;子类实例化过程中又能将参数传递给父类的构造函数中。

2、4 洁净的继承者——原型式继承
* ​原型式继承是对类式继承的一个封装,其中的过渡对象就相当于类式继承的子类,不过在原型式中作为一个过渡对象出现的,其目的是为了创建要返回的新的实例化对象。
栗子:
function inheritObject (obj) {
function F () {}
F.prototype = obj;
return new F();
}

3、多态
* ​js里多态就是同一个方法多种调用方式。方式:对传入的参数做判断以实现多种调用方式。

本章小节:
* 封装与继承式面向对象中的两个主要特性
* 继承是对原有对象的封装,从中创建私有属性、私有方法、共有属性、共有方法、特权方法等。
* 静态属性和方法:不论对类实例化多少次,他们只创建一次,只被类所拥有。
* 两类可被继承的属性和方法:一是在构造函数中,这类属性和方法在对象实例化时被复制一遍;二是在类的原型对象中,这类属性和方法在对象实例化时被所有实例化对象所共有。
* 由类的实例化引出继承。通过原型链继承的方式称为类式继承;通过构造函数继承的方式称为构造函数式继承;将这两种方式组合起来的方式称为组合继承;通过在一个函数内的过渡对象实现继承并返回新对象的方式称为寄生式继承;结合构造函数式继承与寄生式继承的方式称为寄生组合继承。

浅复制中复制对象的方法对象实质是一种指向引用,深复制是把该对象中的引用类型属性细化成值类型拷贝到目标对象中。

猜你喜欢

转载自blog.csdn.net/sunxiaofre/article/details/79674938