JS高程Chapter-6 面向对象程序设计

对JS高级程序设计第六章面向对象程序设计的内容做一个梳理~

属性类型

  • 数据属性
    包含一个数据值的位置。有4个特性:[[configurable]] , [[enumerable]],[[writable]],[[value]]

  • 访问器属性
    不包含数据值,包含一对gettersetter函数。有4个特性:[[configurable]] , [[enumerable]],[[get]],[[set]]
    访问器属性不能直接定义,必须使用Object.defineProperty来定义。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Object.defineProperty(obj, key, {
    configurable:true,
    enumerable:true,
    get:function() {

    },
    set:function(newValue) {

    }
    })

定义多个对象:Object.defineProperties(obj, {})

  • 获取属性的特性
    Object.getOwnPropertyDescripter() 接收两个参数:属性所在的对象和要读取器描述符的属性名称。返回一个对象。

创建对象方法

工厂模式

用函数封装以特定接口创建对象,不使用new,缺点是无法解决对象识别的问题(即怎么知道一个对象的类型).

1
2
3
4
5
6
7
8
9
10
11
12
// 使用函数封装对象
function createPerson(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function() {
console.log(this.name)
}
return o;
}
// 创建对象
var person1 = createPerson('zhangsan', 33);

构造函数模式

用构造函数创建特定类型的对象,使用new.

1
2
3
4
5
6
7
8
9
10
// 创建自定义构造函数,自定义对象类型的属性和方法
function Person(name, age) {
this.name = name;
this.age = age;
this.sayName = function() {
console.log(this.name)
}
}
// 使用new操作符创建对象实例
var person1 = new Person('lisi', 24);

使用new操作符调用构造函数经历了如下4步:

  • 创建一个新对象;
  • 将构造函数的作用域赋给新对象(this指向新对象);
  • 执行构造函数中的代码(为新对象添加属性);
  • 返回新对象。

使用构造函数的缺点是:每个方法都要在每个实例上重新创建一遍。

原型模式

我们创建的每一个函数都有一个prototype(原型)属性,这个属性是一个指针,指向一个对象,这个对象的用途是包含由特定类型的所有实例共享的属性和方法。
那么prototype就是 通过调用构造函数而创建的那个对象实例 的原型对象
使用原型对象可以让所有对象实例共享他包含的属性和方法。

这里就涉及到了原型及原型对象的知识点,将单独列出来说明……

组合使用构造模式和原型模式

最常见的方式。构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function Person(name, age) {
this.name = name;
this.age = age;
this.friends = ['jake', 'rose'];
}

Person.prototype = {
constructor: Person,
sayName: function() {
console.log(this.name)
}
}

var person1 = new Person('zhangsan', 33);
var person2 = new Person('lisi', 24);

person1.friends.push('xiaoming');
console.log(person1.friends); // ['jake', 'rose', 'xiaoming']
console.log(person2.friends); // ['jake', 'rose']
console.log(person1.sayName === person2.sayName); // true

动态原型模式

把原型prototype那部分写在构造函数里面了

1
2
3
4
5
6
7
8
9
10
11
12
13
function Person(name, age) {
// 属性
this.name = name;
this.age = age;
// 方法
if(typeof this.sayName != 'function') {
Person.prototype.sayName = function() {
console.log(this.name);
}
}
}

var person1 = new Person('zangsan', 33);

寄生构造函数模式

创建一个函数,封装创建对象的代码。前面和工厂模式一样,除了使用new操作符并把使用的包装函数叫做构造函数

1
2
3
4
5
6
7
8
9
10
11
function Person(name, age) {
var o = new Object();
o.name = name;
o.age = age;
o.sayName = function() {
console.log(this.name);
}
return o;
}

var person1 = new Person('zhangsan', 22);

缺点是:无法依赖instanceof来确定对象类型。

1
2
console.log(person1 instanceof Person); // false
console.log(person1.constructor === Person); // true

稳妥构造函数模式

与寄生构造函数模式类似,不同的是:创建对象额实例方法不引用this;不使用new操作符调用构造函数。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function Person(name, age) {
// 创建要返回的对象
var o = new Object();

// 在这里定义私有变量和函数

// 添加方法
o.sayName = function() {
console.log(name);
}

return o;
}

var person1 = Person('lisi', 24);

变量person1是一个稳妥对象,除了调用提供的方法,没有别的办法可以访问数据成员。

缺点:无法依赖instanceof来确定对象类型。

继承

JS继承有六种方式:

  • 原型链继承
  • 构造函数继承
  • 组合继承
  • 原型式继承
  • 寄生式继承
  • 组合继承式继承

这章内容有些混乱,还是贴一张思维导图吧
oop面向对象