《重学前端》学习笔记(二)

2019-02-28  本文已影响0人  米开朗基萝

面向对象还是基于对象?

历史问题

不同的编程语言中,设计者利用各种不同的语言特性来抽象描述对象,最为成功的流派是使用“类”的方式来描述对象,这诞生了诸如 C++、Java 等流行的编程语言。
而 JavaScript 早年却选择了一个更为冷门的方式:原型。然而很不幸,因为一些公司政治原因,JavaScript 推出之时受管理层之命被要求模仿 Java,所以,JavaScript 创始人 Brendan Eich 在“原型运行时”的基础上引入了 new、this 等语言特性,使之“看起来更像 Java”。

JavaScript对象的特征

  1. 对象具有唯一标识性:即使完全相同的两个对象,也并非同一个对象。
  2. 对象有状态:对象具有状态,同一对象可能处于不同状态之下。
  3. 对象具有行为:即对象的状态,可能因为它的行为产生变迁。

在 JavaScript 中,将状态和行为统一抽象为“属性”。JavaScript中对象具有高度的动态性,这是因为 JavaScript 赋予了使用者在运行时为对象添改状态和行为的能力。

JavaScript对象的两类属性

对 JavaScript 来说,属性并非只是简单的名称和值,JavaScript 用一组特征(attribute)来描述属性(property)。

  1. 数据属性
  1. 访问器(getter/setter)属性

我们通常用于定义属性的代码会产生数据属性,其中的 writable、enumerable、configurable 都默认为 true。我们可以使用内置函数 Object.getOwnPropertyDescripter 来查看:

var o = { a: 1 };
o.b = 2;
//a 和 b 皆为数据属性
Object.getOwnPropertyDescriptor(o,"a") // {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(o,"b") // {value: 2, writable: true, enumerable: true, configurable: true}

改变属性特征或者定义访问器属性,可以使用Object.defineProperty

var o = { a: 1 };
Object.defineProperty(o, "b", {value: 2, writable: false, enumerable: false, configurable: true});
//a 和 b 都是数据属性,但特征值变化了
Object.getOwnPropertyDescriptor(o,"a"); // {value: 1, writable: true, enumerable: true, configurable: true}
Object.getOwnPropertyDescriptor(o,"b"); // {value: 2, writable: false, enumerable: false, configurable: true}
o.b = 3;
console.log(o.b); // 2

什么是原型

在javaScript之前,原型系统就更多与高动态性语言配合,并且多数基于原型的语言提倡运行时的原型修改,这应该是 Brendan 选择原型系统很重要的理由。

javaScript原型

  1. 如果所有对象都有私有字段 [[prototype]],就是对象的原型;
  2. 读一个属性,如果对象本身没有,则会继续访问对象的原型,直到原型为空或者找到为止。

new 运算接受一个构造器和一组调用参数,实际上做了几件事:

  1. 以构造器的 prototype 属性(注意与私有字段 [[prototype]] 的区分)为原型,创建新对象;
  2. 将 this 和调用参数传给构造器,执行;
  3. 如果构造器返回的是对象,则返回,否则返回第一步创建的对象。

ES6中的类

基本写法

class Rectangle {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
  // Getter
  get area() {
    return this.calcArea();
  }
  // Method
  calcArea() {
    return this.height * this.width;
  }
}

继承能力

class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }

  speak() {
    console.log(this.name + ' barks.');
  }
}

let d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

上一篇下一篇

猜你喜欢

热点阅读