构造函数概念✨
在 JavaScript 中,任何的函数都可以作为构造函数存在,之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数具有以下特点:
1.习惯上首字母大写
2.使用new关键字进行调用
3.构造函数用来新建实例对象
4.内部用this来构造属性和方法
5.构造函数在被调用之后会马上创建一个新对象,并将该对象作为返回值返回
6.具有prototype
构造函数和普通函数的区别👀
1.调用方式和命名
- 普通函数:通常小写,直接调用方法名
- 构造函数:通常首字母大写,需要使用
new关键词调用
// 普通函数:
function person() {}
person()
// 构造函数:
function Person() {}
const p = new Person()
2.this指向
- 普通函数:严格模式下
this表示为undefined,非严格模式下this指向window - 构造函数:
this指向新创建对象的实例
// 普通函数 非严格模式
function person() {
console.log('this === window?', this === window)
}
person() // true
"use strict";
// 普通函数 严格模式
function person() {
console.log('this?', this)
}
person() //undefined
// 构造函数
function Person(city) {
this.city = city
console.log('this指向:', this);
}
const c1 = new Person('杭州') // this指向: Person {city: '杭州'}
const c2 = new Person('北京') // this指向: Person {city: '北京'}
3.return区别
- 普通函数:一般都带return,有值就返回
return后面的值,没有值或者没有写return就返回undefined。 - 构造函数:一般不需要return。如果返回基本类型,
return语句可以忽略。如果返回引用类型,会直接返回引用类型本身。
// 普通函数
function person() {
return 'abc'
}
console.log(person()); // 'abc'
// 构造函数 返回基本类型
function Person(name) {
this.name = name;
return 'abc' // 基本类型自动忽略这行
}
const p = new Person('jayshen')
console.log(p); // Person {name: 'jayshen'}
// 构造函数 返回应用类型
function Person(name) {
this.name = name;
return {
name: 'abc'
}
}
const p = new Person('jayshen')
console.log(p); // {name: 'abc'}
new操作符做了什么❓
我们先来手动实现一个new
1.创建了一个新的空对象
2.设置原型,将对象的原型设置为函数的prototype对象
3.调用函数,this指向新创建的对象
4.返回新创建的对象(判断函数的返回值类型,如果是值类型,返回创建的对象。如果是引用类型,就返回这个引用类型的对象)
function objectFactory() {
let newObj = null
// 获取第一个参数,既传入的构造函数
let Constructor = Array.prototype.shift.call(arguments); // or let Constructor = [].shift.call(arguments)
let result = null
if (typeof Constructor === 'function') {
// 创建一个空对象
newObj = Object.create(Constructor.prototype)
// 使用 apply,改变构造函数 this 的指向到新建的对象,这样 obj 就可以访问到构造函数中的属性
result = Constructor.apply(newObj, arguments)
// 判断返回对象
let flag = result && typeof result === 'object'
return flag ? result : newObj
}
}
function person(name, age) {
this.name = name
this.age = age
}
const p = objectFactory(person, 'JayShen', 18) // 等同于操作符new
console.log(p)
箭头函数能否使用new调用❓
从上面一系列操作可以看出,箭头函数肯定是不可以使用new调用的,原因:
1.箭头函数根本没有自己的this!导致内部的this就是外层代码块的this,最外层就是window,也不能使用call()、apply()、bind() 去改变this的指向。构造函数的this永远指向被他实例化出来的对象,但是箭头函数无法对创建出来的实例进行this绑定。
2.没有原型prototype,就没有super用于访问原型属性。
3.箭头函数和new搭配会报错!(最直接)