• js构造函数


    构造函数

    通过 new 函数名实例化对象的函数叫构造函数。
    任何的函数都可以作为构造函数存在。之所以有构造函数与普通函数之分,主要从功能上进行区别的,构造函数的主要 功能为 初始化对象,特点是和new 一起使用。new就是在创建对象,从无到有,构造函数就是在为初始化的对象添加属性和方法。构造函数定义时首字母大写(规范)。

    function Person(name) {
        this.name = name;
    }
    
    let p1 = new Person('张三'); // 实例化
    
    console.log(p1); // Person {name: "张三"}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    此时,p1就是一个新对象。

    1. new一个新对象的过程,发生了什么?

    1. 创建一个空对象obj {}
    2. 空对象的_proto_指向了构造函数的prototype成员对象
    3. 使用apply调用构造器函数,属性和方法被添加到 this 引用的对象中
    4. 如果构造函数中没有返回其它对象,那么返回 this,即创建的这个的新对象,否则,返回构造函数中返回的对象

    对new理解:new 申请内存, 创建对象,当调用new时,后台会隐式执行new Object()创建对象。所以,通过new创建的字符串、数字是引用类型,而是非值类型。

    2. 手写new函数

    function _new(func, ...args) {
        // 1. 创建空对象
        let obj = {};
        // 2. 空对象的_proto_指向了构造函数的prototype成员对象
        obj.__proto__ = func.prototype; // 一二步合并就相当于 let obj = Object.create(func.prototype)
        // 3. 使用apply调用构造器函数,属性和方法被添加到 this 引用的对象中
        let result = func.apply(obj, args);
    	// 4. 确保 new 出来的是个对象
        return typeof result === 'object' ? result : obj;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    测试用例:

    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    let obj = _new(Person, 'xia', 20);
    
    console.log(obj); // Person {name: "xia", age: 20}
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3. 构造函数上的方法

    1. 在构造函数上直接定义方法(不共享)
    function Person() {
        this.say = function () { // 直接定义方法
            console.log('hello');
        }
    }
    
    let p1 = new Person();
    let p2 = new Person();
    p1.say(); // hello
    p2.say(); // hello
    
    console.log(p1.say === p2.say); // false
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    很明显,p1 和 p2 指向的不是一个地方。 所以 在构造函数上通过 this 来添加方法的方式来生成实例,每次生成实例,都是新开辟一个内存空间存方法。这样会导致内存的极大浪费,从而影响性能

    1. 通过原型添加方法(共享)

    构造函数通过原型分配的函数,是所有对象共享的。

    function Person(name) {
        this.name = name;
    }
    Person.prototype.say = function () { // 通过原型添加方法
        console.log('hello ' + this.name);
    }
    
    let p1 = new Person('张三');
    let p2 = new Person('李四');
    p1.say(); // hello 张三
    p2.say(); // hello 李四
    
    console.log(p1.say === p2.say); // true
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    所以我们经常 将公共属性定义到构造函数里,将公共方法放到原型对象上

    点击查看“构造函数的五种继承方式

  • 相关阅读:
    Hydra参数
    基于深度学习的图像生成与识别技术研究
    .NET、VUE利用RSA加密完成登录并且发放JWT令牌设置权限访问
    uniapp---弹出框组件代码
    【Data Grip】打开控制台编写sql语句
    计算机组成原理-数据的运算
    VertiGIS进入下一增长阶段,任命Andy Berry为首席执行官
    MVC三层架构
    vue动态路由切换刷新保留历史路由搜索条件数据
    wget出现无法建立SSL连接的问题
  • 原文地址:https://blog.csdn.net/x550392236/article/details/133863842