勐海县城乡建设局门户网站,建设了网站怎么管理系统,ios软件资源网站,东莞网站建设lhznkj文章目录 语法不同方法定义方式不同继承方式不同类内部的this指向不同静态成员定义方式不同访问器属性类的类型检查 在JavaScript中#xff0c;类和构造函数都被用来创建对象#xff0c;接下来会从以下几点说说两者的区别#xff1a; 语法不同
构造函数使用函数来定义类使用… 文章目录 语法不同方法定义方式不同继承方式不同类内部的this指向不同静态成员定义方式不同访问器属性类的类型检查 在JavaScript中类和构造函数都被用来创建对象接下来会从以下几点说说两者的区别 语法不同
构造函数使用函数来定义类使用class关键字来定义
ES6 的class可以看作是一个语法糖这种写法只是让对象原型的写法更加清晰、更像面向对象编程的语法。
比如这是一个构造函数生成实例对象的例子
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.toString()) // (1, 2)上面的代码用类来改写是这样的
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.toString()) // (1, 2)所以类完全可以看作构造函数的另一种写法
class Point {// ...
}
typeof Point // function
Point Point.prototype.constructor // true类的数据类型就是函数类本身就指向构造函数。 方法定义方式不同
构造函数的方法都是定义在构造函数的原型上即原型上的方法被所有实例共享类的方法可以直接定义在类中也可以定义在类的原型上而且定义在类中的方法是不可枚举的。 构造函数的prototype属性在 ES6 的“类”上面继续存在。事实上类的所有方法都定义在类的prototype属性上面。 class Point {constructor() {// ...}toString() {// ...}toValue() {// ...}
}
// 等同于
Point.prototype {constructor() {},toString() {},toValue() {},
};以下代码表明类的内部所有定义的方法都是不可枚举的non-enumerable
class Point {constructor(x, y) {// ...}toString() {// ...}
}
Object.keys(Point.prototype) // []
Object.getOwnPropertyNames(Point.prototype) // [constructor,toString]而直接定义在原型上的都是可枚举的
class Point {constructor(x, y) {this.x x;this.y y;}toString() {return ( this.x , this.y );}
}
Point.prototype.toString1 function() {// ...
};console.log(Object.keys(Point.prototype)) // [ toString1 ]
console.log(Object.getOwnPropertyNames(Point.prototype)) // [ constructor, toString, toString1 ]
继承方式不同
构造函数通过将一个构造函数作为另一个构造函数的原型实现原型链继承可以实现单继承和多继承。类通过extends关键字来实现继承支持单继承子类继承父类的属性和方法可以调用父类的构造函数。
构造函数的继承需要手动处理原型链并确保构造函数和原型的正确指向以下示例可看出
function Animal(name) {this.name name;
}Animal.prototype.eat function() {console.log(this.name is eating.);
};function Dog(name, breed) {Animal.call(this, name); // 调用父类构造函数this.breed breed;
}Dog.prototype Object.create(Animal.prototype); // 设置子类的原型对象
Dog.prototype.constructor Dog; // 重设构造函数指向自身Dog.prototype.bark function() {console.log(this.name is barking.);
};const dog new Dog(Buddy, Golden Retriever);
dog.eat(); // 输出: Buddy is eating.
dog.bark(); // 输出: Buddy is barking.类的继承示例
class Animal {constructor(name) {this.name name;}eat() {console.log(${this.name} is eating.);}
}class Dog extends Animal {constructor(name, breed) {super(name); // 调用父类构造函数this.breed breed;}bark() {console.log(${this.name} is barking.);}
}const dog new Dog(Buddy, Golden Retriever);
dog.eat(); // Buddy is eating.
dog.bark(); // Buddy is barking.需要注意的是子类必须在constructor方法中调用super方法否则新建实例时会报错。这是因为子类自己的this对象必须先通过父类的构造函数完成塑造得到与父类同样的实例属性和方法然后再对其进行加工加上子类自己的实例属性和方法。如果不调用super方法子类就得不到this对象。 如果子类没有定义constructor方法这个方法会被默认添加代码如下。也就是说不管有没有显式定义任何一个子类都有constructor方法。
class Dog extends Animal {
}
// 等同于
class Dog extends Animal {constructor(...args) {super(...args);}
}另一个需要注意的地方是在子类的构造函数中只有调用super之后才可以使用this关键字否则会报错。这是因为子类实例的构建基于父类实例只有super方法才能调用父类实例。
class Animal {constructor(name) {this.name name;}
}
class Cat extends Animal {constructor(name, color) {this.color color; // ReferenceErrorsuper(name);this.color color; // 正确}
}类内部的this指向不同
ES5中类内部函数中的this指向调用函数的对象ES6中类内部方法中的this指向实例对象 注意如果静态方法中包含this关键字这个this指的是类而不是实例。
class Foo {static classMethod() {return hello;}}Foo.classMethod() // hello
var foo new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function静态成员定义方式不同
ES5中静态成员需要通过给构造函数手动添加属性或方法来实现
function Person(name, age) {this.name name;this.age age;
}Person.staticMethod function() {console.log(This is a static method.);
};ES6中可以使用static关键字定义静态属性或方法
class Person {constructor(name, age) {this.name name;this.age age;}static staticMethod() {console.log(This is a static method.);}
}访问器属性
ES6中引入了getter和setter方法可以使用get和set关键字定义访问器属性。
class Person {constructor(name, age) {this._name name;this._age age;}get name() {return this._name;}set name(value) {this._name value;}
}var person new Person(Tom, 20);
console.log(person.name); // 输出 Tom
person.name Jerry;
console.log(person.name); // 输出 Jerry在上述例子中通过getter和setter方法定义了name访问器属性可以通过person.name进行属性的访问和修改。
类的类型检查
ES5中可以使用instanceof运算符来判断对象的类型 instanceof 运算符通过检查对象的原型链来确定对象是否是某个构造函数的实例。它会逐级向上查找对象的 __proto__或 prototype属性直到找到与指定构造函数的 prototype 属性相等的对象或到达原型链的末尾。如果找到了相等的对象则返回 true否则返回 false。 function Person() {}
var person new Person();
console.log(person instanceof Person); // 输出 trueES6中可以使用typeof运算符来判断类的类型
class Person {}
var person new Person();
console.log(typeof person); // 输出 object
console.log(typeof Person); // 输出 function在上述例子中typeof person返回objecttypeof Person返回function可以看出在ES6中类的类型也是object类本身的类型是function。