js基础--构造函数

99 阅读2分钟
function Person(){
    this.type='person';
}

首先从表象看,构造函数,就是前面多了一个new关键字。但是,如果想深入得了解它,就要说一下构造函数和普通函数的区别,以及,构造函数前面的new 发生了什么,接着还要介绍下,为什么箭头函数不能作为构造函数,不能new

  1. 构造函数和普通函数的区别 构造函数调用的时候前面有new,普通函数没有
    const p = new Person();
    const p = Person();
  • this指向不同 构造函数的this指向的是构造出来的对象实例,而普通函数在不改变this(比如调用的时候通过显式或者隐式等其他各种改变this)的情况下,指向的是环境对象,浏览器就指向wnidow, node指向global.
  • return的结果不同 构造函数默认是不用return返回值的,因为new关键字起的作用之一就是有返回值,但是普通函数并没有构造函数的默认返回值。关于构造函数的返回值,这里值得关注下,如果我们让一个构造函数返回,boolean, string, number, null, undefined(等基础数据),和object, array等引用数据,那么实际会返回什么呢? 先来剧透一波,如果return的是基本数据,那么构造函数实际返回,会无视return设置值,返回创建的对象实例。如果return的是引用数据,return会覆盖创建实例,构造函数返回自己手写的引用类型值。

我们来验证一下

console.table(
    [null, undefined, 1, true, '', Symbol(), {a: 1}, [1,2]].map(v=> [
        v,
        function(){
            return v;
        },
     ]).map(([item, myConstructor])=>[
         Object.prototype.toString.call(item),
         item,
         JSON.stringify(new myConstructor()),
     ])
)

WechatIMG127.jpeg

2. 构造函数前面的new到底干了什么? 要想知道,new干了什么,那么我们来使用js实现一下new

// 接收不定个数参数,第一个参数是构造函数,后续是被构造函数使用的参数
function myNew(fn, ...args){
    //1: 创建一个空对象
    const obj = {};
    //2: 将新对象__proto__属性连接到构造函数的原型对象上,建立继承关系
    obj.__proto__ = fn.prototype;
    //3: 改变this指向为新创建出来的对象实例
    const res = fn.apply(obj, args);
    //4: 设定返回值,判断是否是引用数据类型
    return typeof res === 'object' ? res :  obj


3.箭头函数可以当构造函数吗? 答案是不能但是为什么呢?

WechatIMG2389.jpeg

我们可以看到,箭头函数相对于普通函数

  • 没有prototype(无法将新对象__proto__属性连接到构造函数的原型对象上)
  • 没有arguments
  • 没有caller(无法确定上下文) 所以,new 的过程中,箭头函数很多都不能满足。