当前位置: 首页 > 新闻动态 > 猜您喜欢 >

前端面试必备:JavaScript中构造函数与class的区别总结

作者:深圳纯量网络 阅读: 发布时间:2024-08-17 09:03

摘要:一、构造函数首先,构造函数其实就是JavaScript程序中定义好的函数,我们可以直接使用。构造函数实际也是一种函数,它是专门用于生成定义对象,...

js构造函数面试题_前端面试算法和数据结构_

一、构造函数

首先,构造函数其实就是JavaScript程序中定义好的函数,我们可以直接使用。构造函数实际也是一种函数,它是专门用于生成定义对象,通过构造函数生成的对象,称为实例化对象。

构造函数分为两种,一种是JavaScript程序定义好的构造函数,我们成为称为内置构造函数,另外一种是程序员自己定义的构造函数,称为自定义构造函数。

构造函数虽然也是一种函数,但是和普通函数是区别的:

1、构造函数一定要和关键词new一起使用,new关键词会自动的给构造函数定义一个对象,并且返回这个对象,我们只要对这个对象设定属性,设定方法就可以使用。

2、构造函数为了和其他函数区别,语法规范规定构造函数的函数名称,第一个字母必须大写,使用大驼峰命名法。

3、构造函数给对象定义属性和方法的语法,与一般函数不同

//自定义构造函数
function Person(name,sex,age,addr){
  // 定义属性
  this.name = name;
  this.sex = sex;
  this.age = age;
  this.addr = addr;
  // 定义方法
  this.fun = function(){
    console.log(this.name,this.sex,this.age,this.addr);
  }
}
// 生成实例化对象
const person = new Person('终结者','男',28,'杭州');
console.log(person); //输出实例化对象

普通构造函数实现继承

//普通构造函数继承
//动物
function Animal() {
    this.eat = function () {
        console.log('animal eat')
    }
}
 
//狗
function Dog() {
    this.bark = function () {
        console.log('dog bark')
    }
}
//绑定原型,实现继承
Dog.prototype = new Animal()
//哈士奇
var hashiqi = new Dog()

js构造函数面试题__前端面试算法和数据结构

二、class

ES6构造函数语法:ES6与ES5构造函数语法对比,其功能作用完全相同,只是语法不同。ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

class Perosn{// ES6class方法定义构造函数
  //constructor是构造器,定义实例化对象的属性和属性值, ()中的是参数
  constructor (name,age,sex){
    this.name = name;
    this.age = age; 
  	this.sex = sex;
	}
  //定义方法,虽然没声明,但是也是定义在构造函数中的prototype中
  printAll(){
  	console.log(this.name,this.age,this.sex);
	}
}
// 生成实例化对象
const test = new Perosn('终结者','男',28,'杭州');
console.log(person);//输出实例化对象
person.printAll();  //输出方法

上面代码定义了一个“类”,可以看到里面有一个constructor方法,这就是构造方法,而this关键字则代表实例对象。也就是说,ES5的构造函数Person,对应ES6的Person类的构造方法。

定义“类”的方法的时候,前面不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。

Class实现继承

class Animal{
    constructor(name){
        this.name=name
    }
    eat(){
        console.log(this.name +'eat');
    }
}
class Dog extends Animal{
    constructor(name){
        super(name)//访问和调用Dog对象的父对象Animal上的函数。
        this.name=name
      // 在派生类中, 必须先调用 super() 才能使用 "this",忽略这个,将会导致一个引用错误。
    }
    bark(){
        console.log(this.name+'bark');
    }
}
const dog=new Dog("泰迪");
dog.eat();
dog.bark();

构造函数的prototype属性,在ES6的“类”上面继续存在。事实上,类的所有方法都定义在类的prototype属性上面。

ES6中的class语法就是ES5中构造函数的另一种写法,一种更高级的写法,

class语法的底层还是ES5中的构造函数,只是把构造函数进行了一次封装而已。

ES6出现的目的为了让我们的让对象原型的写法更加清晰、在语法上更加贴合面向对象的写法、更像面向对象编程让JavaScript更加的符合通用编程规范,即大部分语言对于类和实例的写法,class实现继承更加容易理解,更易于后端语言使用。

_前端面试算法和数据结构_js构造函数面试题

三、构造函数与Class的区别

类不存在变量提升(hoist),这一点与 ES5 完全不同。

 // ES5
var bar  = new Bar(); // 可行
function Bar() {
  this.bar = 42;
}
    
//ES6
const foo = new Foo(); // Uncaught ReferenceError
class Foo {
  constructor() {
    this.foo = 42;
  }
}

类和模块的内部,默认就是严格模式,所以不需要使用use strict指定运行模式。只要你的代码写在类或模块之中,就只有严格模式可用。考虑到未来所有的代码,其实都是运行在模块之中,所以 ES6 实际上把整个语言升级到了严格模式。

// ES5
function Bar() {
  // 引用一个未声明的变量
  baz = 42; // it's ok
}
var bar  = new Bar(); 
// ES6
class Foo {
  constructor(){
    // 引入一个未声明的变量
    fol = 42;
    // Uncaught ReferenceError: fol is not defined
  }
}
let foo = new Foo();

ES6 中的 class,它的方法(包括静态方法和实例方法)默认是不可枚举的,而构造函数默认是可枚举的。细想一下,这其实是个优化,让你在遍历时候,不需要再判断 hasOwnProperty 了

// ES5
function Bar() {}   
Bar.answer = function () {};
Bar.prototype.print = function () {};
console.log(Object.keys(Bar));// ["answer"]
console.log(Object.keys(Bar.prototype))// ["print"]
// ES6
class Foo {
	constructor(){}
  static answer() {}
  print(){}
}
console.log(Object.keys(Foo))// []
console.log(Object.keys(Foo.prototype));// []

class 必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。

// ES5
function Bar(){ }
var bar = Bar();// it's ok;
// ES6
class Foo {
}
let foo = Foo();
// Uncaught TypeError: Class constructor Foo cannot be invoked without 'new'

// ES5 
function Bar() {
	Bar = 'Baz';
	this.bar = 42;
}
var bar = new Bar();
console.log(bar);// Bar {bar: 42}
console.log(Bar);// 'Baz'
// ES6
class Foo {
	constructor(){
		this.foo = 42;
		Foo = 'Fol'; // Uncaught TypeError: Assignment to constant variable.
	}
}
let foo = new Foo();
Foo = 'Fol';// it's ok

一条是:子类的__proto__指向父类

另一条:子类prototype属性的__proto__属性指向父类的prototype属性.

ES6的子类可以通过__proto__属性找到父类,而ES5的子类通过__proto__找到Function.prototype

// ES5
function Super() {}
function Sub() {}
Sub.prototype = new  Super();
Sub.prototype.constructor = Sub;
var sub = new Sub();
console.log( Sub.__proto__ === Function.prototype);// true
// ES6
class Super{}
class Sub extends Super {}
let sub = new Sub();
console.log( Sub.__proto__ === Super);// true

ES5的继承是先建立子类实例对象this,再调用父类的构造函数修饰子类实例(Surper.apply(this))。

ES6的继承是先建立父类实例对象this,再调用子类的构造函数修饰this。即在子类的constructor方法中必须使用super(),之后才能使用this.

// ES5
function MyES5Array() {
	Array.apply(this, arguments);
  // 原生构造函数会忽略apply方法传入的this,
  //即this无法绑定,先生成的子类实例,拿不到原生构造函数的内部属性。
}
MyES5Array.prototype = Object.create(Array.prototype, {
	constructor: {
    value: MyES5Array,
    writable: true,
    configurable: true,
    enumerable: true
   }
})
var arrayES5 = new MyES5Array();
arrayES5[0] = 3;
console.log(arrayES5.length);// 0 
arrayES5.length = 0;
console.log(arrayES5[0]);// 3
// ES6
class arrayES6 extends Array {
	constructor(...args){
		super(...args);
	}
}
let arrayes6 = new arrayES6();
arrayes6[0] = 3;
console.log(arrayes6.length);// 1
arrayes6.length = 0;
console.log(arrayes6[0]);// undefined

需要注意一点:

ES6的class语法无法执行预解析,是不能被提前调用;

ES5的function函数可以提前调用,但是只能调用属性不能调用方法。

  • 原标题:前端面试必备:JavaScript中构造函数与class的区别总结

  • 本文由深圳纯量网络小编,整理排版发布,转载请注明出处。部分文章图片来源于网络,如有侵权,请与纯量网络联系删除。
  • 微信二维码

    CLWL6868

    长按复制微信号,添加好友

    微信联系

    在线咨询

    点击这里给我发消息QQ客服专员

    点击这里给我发消息电话客服专员

    在线咨询

    免费通话


    24h咨询☎️:132-5572-7217


    🔺🔺 24小时客服热线电话 🔺🔺

    免费通话
    返回顶部