跳至主要內容

JavaScript

LincZero大约 3 分钟

JavaScript

目录

对象和类

基于类 vs 基于对象

对于C++程序员,JavaScript最难的就是它的对象模型

  • 基于对象的面向对象语言(object-based):JavaScript
  • 基于 类 的面向对象语言:C++、C#、Java、Simula、Smalltalk

基于对象的面向对象语言,一些具体体现

  • 对象本质上是一个属性集,属性随时可以被添加、删除、修改
  • 对于C++和Java开发者来说,一个普遍的错误就是在访问对象属性时忘记使用this关键字
  • typeof 与 instanceof
    • var shape = new Shape(10,20);中,如果在shape变量使用typeof操作符,则数据类型是Object而不是Shape
    • 如果想确定Shape构造函数是否创建了对象,可以使用instanceof操作符shape instanceof Shape;返回true
  • 允许任何函数作为构造函数,构造函数也可以作为普通函数得到调用
  • ECMAScript中,函数被看作一等公民(Python也是,C/C++或Java不是)
  • 对象实例与备份
    • JavaScript
      • 创建对象时每个实例都保存属性集(包括数据和函数的全部属性)的一个备份
      • 但应用中对于里面的一些像函数的属性,往往只需要保存一次而不是保存在每个实例中
      • 这时可以用原型法来达到这个目的:Shape.prototype.manhattanPos = function(){...}
      • 原型(prototype)的使用详见 “原型与原型链” 一章
    • C++(函数不是一等公民)
      • 类的函数实现(.cpp)整个程序只保存一份
      • 类的头文件(.h)保存在每个调用的cpp文件中
      • 头文件定义的成员变量数据保存在每个实例中
      • 头文件定义的静态成员变量整个程序只保存一份(枚举也是)
    • 注意项
      • 这种区别,与函数在JavaScript中是【一等公民】而在C++中不是有关(C++中函数与数据被 “分别对待”)
      • js中原型法对只读属性(包括成员函数)有用,然而不能给共享变量赋新值,取而代之的是可以创建一个新的同名变量以覆盖原型中的原有属性
  • 继承
    • 基于类中可以使用类继承
    • ECMAScript基于对象中可以使用原型链达到类似的效果
    • 可以使用instanceof操作遍历原型链,以判断哪个构造函数被调用了

举例(配合上面的具体体现来看)

function Shape(x, y){	// 构造函数
    this.x = x
    this.y = y
    this.manhattanPos = function(){
        return Math.abs(this.x) + Math.abs(this.y)
    }
    this.translate = function(dx, dy) {
        this.x += dx
        this.y += dy
    }
}

var shape = new Shape(10, 20)
shape.translate(100, 100);
print(shape.x + "," + shape.y + "(" + shape.manhattanPos() + ")")

对象与类

(无需定义类可直接创建对象,JS中几乎“所有事物”都是对象)

var person=new Object()
person.firstname="Bill"
var person2 = {
    firstName:"Bill"
}

JavaScript有点令人困惑,因为它是动态的,并且本身不提供一个class实现

Class

JavaScript 语言中,生成实例对象的传统方法是通过构造函数。下面是一个例子。

function Point(x, y) {
  this.x = x;
  this.y = y;
}

Point.prototype.toString = function () {
  return '(' + this.x + ', ' + this.y + ')';
};

var p = new Point(1, 2);

而函数的原型链又类似于类继承一样的东西

上面这种写法跟传统的面向对象语言(比如 C++ 和 Java)差异很大,很容易让新学习这门语言的程序员感到困惑。

在 ES2015/ES6 中引入了 class 关键字,但那只是语法糖,JavaScript 仍然是基于原型的

ES6:

class Person {
    constructor(name, age) {  // 构造器
        this.name = name
        this,age = age;
    }
}
class Student extends Person { } // 继承