面向对象的JavaScript

Author Avatar
Silas Shen 10月 30, 2017

面向对象的JavaScript

对象属性

数据属性

  • configurable: 表示能否通过delete删除属性从而重新定义属性,或能否将属性修改为访问器属性
  • enumberable: 表示能否通过for-in循环返回属性
  • writeable: 表示能否修改属性的值
  • value: 包含这个属性的数据值,读属性的时候从这个位置读;写入属性值的时候,把新值保存在这个位置

object.defineProperty()

通过defineproperty()来修改属性默认的特性,接收三个参数(属性所在的对象,属性的名字,一个描述符对象)

var person = {};
Object.defineproperty(person,"name",{
  writeable: false;
  value: "fan"
});

console.log(person.name) //fan
person.name = "dan";
console.log(person.name) //fan

访问器属性

  • configurable: 表示能否通过delete删除属性从而重新定义属性,或者能否将属性修改为数据属性
  • enumberable: 表示能否通过for-in循环返回属性
  • get: 读取属性时调用的函数
  • set: 写入属性时调用的函数

创建对象

工厂模式

function person(name,age,sex) {
  var o = new Object();
  o.name = name;
  o.age = age;
  o.sex = sex;
  return o;
}
var person1 = preson("fan",22,"male");
  • 优点:解决了重复创建多个相似对象的问题
  • 缺点:无法确定对象的类型

构造函数模式

function Person(name,age,sex) {
  this.name = name;
  this.age = age;
  this.sex = sex;
}
var person2 = new Person("dan",20,"male")
//new的过程
// 1. 创建一个新的对象
// 2. 将构造函数的作用域赋给新的对象(即this指向了新的对象)
// 3. 执行构造函数的代码(为新的对象添加属性)
// 4. 返回新的对象
  • 可以确定确定对象的类型
  • 每个方法都要在每个实例上重新创建一遍

原型模式

function Person() {
}
Person.prototype.name = 'fan';
Person.prototype.age = 25;
Person.prototype.sayName = function() {
  alert(this.name)
}
// 更简洁的原型语法
Person.prototype = {
  name: 'fan',
  age: 25,
  sayName: function() {
    alert(this.name);
  }
}
var person1 = new Person();
person1.sayName() // 'fan'
person1.name = 'wen';
person1.sayName() // 'wen' => 来自实例
var person2 = new Person();
person2.sayName() // 'fan' => 来自原型

组合

// 组合使用构造模式和原型模式
function Person() {
  this.name = name;
  this.age = age;
}
Person.prototype = {
  constructor: Person,
  sayName: function() {
    console.log(this.name)
  }
}

继承

原型链继承

function SuperType() {
  this.colors = ['red', 'black', 'green'];
}
function SubType() {
}
SubType.prototype = new SuperType();
var instance1 = new SubType();
instance1.colors.push('blue');
var instance2 = new SubType();
// 问题:影响其他的实例
console.log(instance2.colors); // "red, black, green, blue"

构造函数继承

function SuperType() {
  this.colors = ['red', 'black', 'green'];
}
function SubType() {
  // 继承了superType
  SuperType.call(this);
}
var instance1 = new SubType();
instance1.colors.push('blue');
var instance2 = new SubType();
// 不会影响其他的实例
console.log(instance2.colors); // "red, black, green"

组合继承

// 组合继承
function SuperType() {
  this.colors = ['red', 'black', 'green'];
  this.name = name;
}
SuperType.prototype.sayName = function() {
  console.log(this.name);
}
function SubType(name, age) {
  // 继承属性
  SuperType.call(this, name); // 第二次调用SuperType()
  this.age = age;
}
// 继承方法
SubType.prototype = new SuperType(); // 第一次调用SuperType()
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function() {
  console.log(this.age);
}
var instance1 = new SubType('fan', 25);
instance1.colors.push('blue');
console.log(instance1.colors); // "red, black, green, blue"
instance1.sayName(); // 'fan'
instance1.sayAge(); // '25'

var instance2 = new SubType('dan', 24);
console.log(instance2.colors); // "red, black, green"
instance2.sayName(); // 'dan'
instance2.sayAge(); // 24
  • 缺点:调用两次超类型构造函数

ES6

class Point {

}

class ColorPoint extends Point{
  constructor(x, y, color) {
    //调用父类的constructor
    super(x, y);
    this.color = color;
  }

  toString() {
    //调用父类的toString()
    return this.color + ' ' + super.toString();
  }
}