JS class和function的区别

194 阅读2分钟

相同点

1. 都可作为构造函数

函数作为构造函数

如下代码,函数作为构造函数的写法。函数中的this是指向构造函数创建的实例p

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);
console.log(p) // Point {x: 1, y: 2}

class作为构造函数

类包含构造函数、实例方法、取值函数getter、存值函数setter、静态方法、静态属性、私有方法、私有属性但这些都不是必须的。

下面方法定义了一个“类”,可以看到里面有一个constructor()方法,这就是构造方法,而this关键字则代表实例对象。

定义toString()方法,就是实例方法,类的所有实例方法都定义在类的prototype属性上面。 前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法与方法之间不需要逗号分隔,加了会报错。

使用的时候,也是直接对类使用new命令,跟构造函数的用法完全一致。

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

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

var p = new Point(1, 2);
console.log(p) // Point {x: 1, y: 2}

不同点

1. class构造函数必须用new操作符

class构造函数与function构造函数的主要区别为,调用class构造函数必须使用new操作符。而普通function构造函数如果不使用new调用,那么会以全局的this(在浏览器中是window)作为内部对象。

如下代码,普通function函数把window作为this

function point(){}
var p = Point();

调用class构造函数如果忘记使用new命令,将会报错。

class Point {
 // ...
}

// 报错
var point = Point(2, 3); // Uncaught SyntaxError: Identifier 'Point' has already been declared

// 正确
var point = new Point(2, 3);

2. class声明不可以提升

function构造函数声明存在提升,如下代码是不会报错的。

const usr = new Foo('Jack'); 
console.log(usr); // Foo { name: 'Jack' } 
function Foo(name) { 
    this.name = name; 
}

类不存在变量提升(hoist)。

const usr = new Foo('Jack'); // ReferenceError: Foo is not defined
console.log(usr); 
class Foo { 
    constructor(name){
        this.name = name; 
    }
}

3. class不可以用call、apply、bind改变执行上下文改变其this指向。

普通function构造函数是可以通过 call apply bind。如下代码sayName调用call改变其thisobj对象上,输出的name就是obj中的name

function sayName() { 
    console.log(this.name); 
} 
const obj = { name: 'Jack', }; 
sayName.call(obj); // Jack

class使用callapplybind改变this指向则会报错。

class sayName { 
    constructor(){
        console.log(this.name); 
    }
} 
const obj = { name: 'Jack', }; 
sayName.call(obj); // Jack

4. 类的内部所有定义的方法,都是不可枚举的,函数定义的方法是可以枚举的。

function构造函数的方法是可以枚举的,如下使用Object.keys获取prototype上的方法名,会打印出prototype上的方法

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

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

console.log(Object.keys(Point.prototype)) // ['toString']

class类内部定义的方法都是不可以枚举的,如下代码Object.keys(Point.prototype)打印出的是空数据

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

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

console.log(Object.keys(Point.prototype)) // []

参考:

JavaScript class和function的区别