JavaScript开发者应懂的33个概念25-工厂函数和类

JavaScript开发者应懂的33个概念25-工厂函数和类

目录

  1. 调用堆栈
  2. 原始类型
  3. 值类型和引用类型
  4. 隐式, 显式, 名义和鸭子类型
  5. == 与 ===, typeof 与 instanceof
  6. this, call, apply 和 bind
  7. 函数作用域, 块级作用域和词法作用域
  8. 闭包
  9. map, reduce, filter 等高阶函数
  10. 表达式和语句
  11. 变量提升
  12. Promise async 与 wait
  13. 立即执行函数, 模块化, 命名空间
  14. 递归
  15. 算法
  16. 数据结构
  17. 消息队列和事件循环
  18. setTimeout, setInterval 和 requestAnimationFrame
  19. 继承, 多态和代码复用
  20. 按位操作符, 类数组对象和类型化数组
  21. DOM 树和渲染过程
  22. new 与构造函数, instanceof 与实例
  23. 原型继承与原型链
  24. Object.create 和 Object.assign
  25. 工厂函数和类
  26. 设计模式
  27. Memoization
  28. 纯函数, 函数副作用和状态变化
  29. 耗性能操作和时间复杂度
  30. JavaScript 引擎
  31. 二进制, 十进制, 十六进制, 科学记数法
  32. 偏函数, 柯里化, Compose 和 Pipe
  33. 代码整洁之道

简介

记录一个重新学习javascript的过程 ,文章并不是按顺序写的,写完就会更新目录链接 本篇文章目录是参照 @leonardomso 创立,英文版项目地址在这里

前言

本篇文章分为四个部分

  1. 工厂函数和构造函数的区别
  2. ES6的类

1.工厂函数和构造函数的区别

看一个例子

function person(firstName, lastName, age) {
  const person = {};
  person.firstName = firstName;
  person.lastName = lastName;
  person.age = age;
  return person;
}

上述代码,创建一个新对象,并将传递参数作为属性附加到该对象上并返回新对象。 这是一个简单的 JavaScript 工厂函数

实际上工厂函数也很好理解了:

  • 它是一个函数。
  • 它用来创建对象。
  • 它像工厂一样,“生产”出来的函数都是“标准件”(拥有同样的属性)

我们来使用一下工厂函数,

const person1 = person('张', '三', 18);
const person2 = person('李', '四', 20);
console.log(person1);
console.log(person2);

image-20231104093029928

只需要传入一个正确的参数,就可以获取你所需要的对象,而无需知道其创建细节

console.log(person1.constructor=Object);//true
console.log(person1.constructor=person);//false

使用构造函数改造一下

function Person(firstName, lastName, age) {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
}
const person3 = new Person('王', '二', 30);
console.log(person3);

二者写法的不同之处

1.没有显示地创建对象
2.直接将属性和方法赋值给了this
3.没有return语句,还应当注意到 Person的名字使用的是大写的P

我的理解,构造函数就相当于是创建了一个class类,创建实例的话,就是用new 创建,这种创建实例的方式,更像是es6的class。
总之,构造函数本身也是函数,只不过可以用来创建对象而已。
要创建Person的新实例,必须使用new操作符。以这种方式调用构造函数,实际上会有以下4个步骤。

1.创建一个新对象
2.将构造函数的作用域赋值给新对象(因此this就指向了这个新对象)
3.执行构造函数中的代码(为这个新对象添加属性)
4.返回新对象

构造函数的可以通过原型链来实现对象的继承和共享方法。所以说,工厂函数通常用于创建简单对象,而构造函数通常用于创建具有行为和状态的对象

console.log(person1.constructor=Object);//false
console.log(person1.constructor=Person);//true

2.ES6的类

实际上,类是“特殊的函数”,就像你能够定义的函数表达式和函数声明一样,类语法有两个组成部分:类表达式类声明

2.1类声明

定义类的一种方法是使用类声明。要声明一个类,你可以使用带有class关键字的类名(这里是“Penson”)。定义类的开头字母要大写

class Person {
    constructor(firstName, lastName,age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age
	}
}

2.2提升

函数声明和类声明之间的一个重要区别在于,函数声明会提升,类声明不会。你首先需要声明你的类,然后再访问它,否则类似以下的代码将抛出ReferenceError:

函数声明这样写不会报错

const person2 = new Person('王', '二', 30);
console.log(person2);
function Person(firstName, lastName, age) {
    this.firstName = firstName
    this.lastName = lastName
    this.age = age
}

但是类声明这样写会报错

const person2 = new Person('王', '二', 30)//报错
class Person {
    constructor(firstName, lastName,age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age
    }
}

2.3 类表达式

类表达式是定义类的另一种方法。类表达式可以命名或不命名。命名类表达式的名称是该类体的局部名称

//匿名类
const Person = class {
    constructor(firstName, lastName,age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age
    }
}
console.log(Person.name);//输出Person
// 命名类
const Person = class Person2{
    constructor(firstName, lastName,age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age
    }
}
console.log(Person.name);//输出Person2

2.3 constructor()

constructor方法是类的默认方法,通过**new命令生成对象实例时,自动调用该方法**,默认返回实例对象(即this)。一个类必须有constructor方法,如果没有手动定义,JS引擎会自动为它添加一个空的constructor方法

class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    call() {
        console.log(`我叫${this.name}, 今年${this.age}`);
    }
    play(ball) {
        console.log(`我爱玩${ball}`);
    }
}
var p5 = new Person("Tom", 18);
p5.call(); // 我叫Tom, 今年18岁
p5.play("足球"); // 我爱玩足球
Person.prop = 1;
console.log(Person.prop) // 1

实例对象身上有自身的属性,那class本身也会有自己的属性,也就是静态属性:

2.4 static静态方法

敲黑板了,凡是被static修饰的属性和方法都是静态方法和属性,只能被类名调用,不能被实例化对象调用.同时也不能被子类继承,换句话说它属于当前这个类的.

class Person {
    constructor() {}
    call() {

        console.log(`我是实例方法`);

    }
    static staticFn() {

        console.log(`我是静态方法`,this);

    }
}
var p6 = new Person("Tom", 18);
p6.call();//我是实例方法
Person.staticFn();//我是静态方法
p6.staticFn();//报错

2.5 extends 类的继承

class之间可以通过extends关键字实现继承(继承父类的所有属性和方法)

// 父类
class Person {
    constructor(name, age) {
        this.name = name;
        this.age = age;
    }
    call() {
        console.log(`我叫${this.name}, 今年${this.age}`);
    }
    play(ball) {
        console.log(`我喜欢玩${ball}`);
    }
}
// 子类
class Student extends Person {
    constructor(name, age, score) {
        super(name, age);
        this.score = score;
    }
    // 重写父类的方法
    call() {
        console.log(
            `我叫${this.name},今年${this.age}岁, 考了${this.score}`
        );
    }
    //如果子类中定义了构造函数,那么它必须先调用 super() 才能使用 this
}
var s1 = new Student("Tom", 18, 99);
s1.play("篮球"); // 我喜欢玩篮球
s1.call(); // 我叫Tom,今年18岁, 考了99分

从上面的案例中我们可以看到,当子类中出现与父类同名的方法时,会将父类的方法进行重写,从而使得子类实例能获取到最新的结果。

super

从上一个继承案例中我们可以发现有一个super关键字,子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。

总结

  • class类是基于原型的继承的语法糖;
  • class的出现使得代码更加优雅,代码量减少;
  • class类能清晰的指定构造函数和抽象方法;
  • class类在声明时就可以设定属性和方法,不需要再往函数的原型中添加方法;
  • 使用class类时必须实例化;
  • 使用extends关键字实现继承。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值