构造函数:

构造函数本质上还是函数

只是 是 一个专门用来创建对象 的函数

通过构造函数创建的对象 本质上还是一个对象称为 实例化对象

实例化对象,本质上,就是一个对象,只是由 构造函数创建的

定义构造函数时,不要写 创建对象 也不要写 返回对象

也就是 不要写 const obj = {} 也不要写 return obj
构造函数,一定不要写 return 会与 new关键词的 return冲突

将构造函数与 new 关键词 联动使用 new 关键词 会自动的创建一个对象,并且返回这个对象

JavaScript语法规定,构造函数的this,指向的是通过这个构造函数出,创建的对象的名称

如果创建时,对象叫obj1,此时this,指向的就是obj1这个对象
下一次,创建的对象叫 ojbaaa,此时this,指向的就是objaaa这个对象

为了区别 普通函数 和 构造函数JavaScript语法规范规定

构造函数,使用 大驼峰命名法
普通函数,使用 小驼峰命名法
    // 定义构造函数
    function CreateObj(start , end){
        // 不要创建对象
        // 构造函数中的 this 指向 创建的 对象
        this.start = start;
        this.end = end;
        this.fun = function(){
            let res = 0;
            for (let i = this.start; i <= this.end; i++) {
                res += i;
            }
            return res;
        }
        // 不要返回对象
        // new 关键词 都会给你干了
    } 
    // 使用构造函数
    // 必须要与 new 关键词 联动
    const obj = new CreateObj( 1, 100 );
    console.log(obj.fun());  //5050
    console.log(obj);  //CreateObj

原型 / 原型属性

如果将所有的属性属性值 和 函数方法 都定义在 实例化对象中就造成了相同的函数方法 定义给每一个对象造成了代码的重复冗余

解决方案:

属性属性值,每一个对象都会不同,就定义在对象本身上
函数方法,完全相同的,只是每一个对象都要调用使用
将函数方法,定义在 构造函数中 ,每一个通过这个构造函数生成的实例化对象,都可以调用

这个时候可以使用原型属性

1, 每一个 函数 天生都有一个 特殊的 公共空间 , 叫 prototype
2, 存储在 这个 公共空间中的数据 函数方法 可以被 调用
3, 所有通过这个构造函数 生成的实力话对象,都可以调用
4, prototype 本质上是一个 对象
    function CreateObj1(start, end) {
        this.start = start;
        this.end = end;
        // 将 函数方法 fun 定义在 实例化对象上
        this.fun = function () {
            let res = 0;
            for (let i = this.start; i <= this.end; i++) {
                res += i;
            }
            return res;
        }
    }

    const obj1 = new CreateObj1(1, 100);
    console.log(obj1);
    console.log( obj1.fun() )

    function CreateObj2(start, end) {
        this.start = start;
        this.end = end;
    }
    CreateObj2.prototype.fun = function () {
        let res = 0;
        for (let i = this.start; i <= this.end; i++) {
            res += i;
        }
        return res;
    }

    const obj2 = new CreateObj2(1, 100);
    console.log(obj2);
    console.log( obj2.fun() )

原型对象和原型属性

原型对象 / 原型   prototype

原型对象: 是 每一个函数, 天生就有的 特殊的 公共的 存储空间
每一个通过 构造函数生成的实例化对象 都可以访问代用这个 空间中 存储的内容
prototype 本质上是一个对象

原型属性  __proto__

原型属性: 是 每一个对象, 天生都有的 属性
__proto__ 本质上 是一个 对象
__proto__ 存储的内存的地址 就是 生成这个实例化对象 的 构造函数的 prototype 内存地址
也就是 实例化对象,通过访问 __proto__ 本质 就是 访问 prototype
每一个 实例化对象的 __proto__ 就是 生成这个实例化对象 的 构造函数的 prototype

调用数据原则: 就近原则

自己有用自己,自己没有找爹的

实例化对象自己有的属性,调用自己的
自己没有的属性,通过 __proto__ 找 构造函数 prototype ,如果有就调用

如果需要执行调用 prototype 公共空间中的数据,就要写

对象.__proto__.属性

一般情况下,prototype 公共空间中,只写 函数方法,不写属性

    function Fun(){
        // 定义在构造函数中的,会直接定义在实力话对象上
        // 实力话对象,就会有属性 name age 
        this.name = '张三';
        this.age= 18;
    }
    Fun.prototype.fun = function(){};
    Fun.prototype.sex = '男';
    Fun.prototype.add = '北京';

    const obj = new Fun();
    obj.sex = '不知道';

    console.log(obj);  //Fun age: 18 name: "张三" sex: "不知道" __proto__: Object
    console.log(obj.name);  //张三
    // 自己有调用自己的,自己没有调用 构造函数 prototype的
    console.log(obj.sex);  //不知道
    // 不用自己的,直接用 构造函数 prototype的
    console.log(obj.__proto__.sex);  //男

一沙一世界,一花一天堂。君掌盛无边,刹那成永恒。