美文网首页
javascript 原型

javascript 原型

作者: wyc0859 | 来源:发表于2022-03-05 21:10 被阅读0次

    函数也是一个对象,当真正开始执行函数,执行环境会为函数分配2个空间:
    函数对象变量空间、函数对象空间

    函数对象变量空间:存在栈中,用函数名表示。
    函数对象空间:存在堆中,开辟一个内存空间,这空间中有个默认的prototype属性(它就是原型对象属性,指向原型对象空间)

    function funa() {
      console.log("this is funa");
    }
    funa(); //this is funa
    console.log("funa.name:", funa.name); // 栈中  funa
    console.log("funa.prototype:", funa.prototype); //堆中 {constructor: ƒ}
    console.log("funa.__proto__:", funa.__proto__); //堆中 ƒ () { [native code] }
    
    image.png

    函数 和 构造函数的区别

    当通过 new 函数()时,此刻这个函数就是构造函数
    当执行环境执行 new 构造函数时,构造函数中通过 this 定义的属性和方法会分配到,这个实例对象空间中
    构造函数所有实例对象都可以访问 原型对象空间上的属性和方法。

    function people(name, age, sex) {
      this.name = name;
      this.age = age;
      this.sex = sex;
    }
    
    //实例对象  <=  构造函数
    const a = new people("小a", 18, "女");
    const b = new people("小b", 19, "男");
    
    console.log('a实例对象:', a);  //people {name: '小a', age: 18, sex: '女'}
    console.log('a.name:', a.name);  //小a
    console.log('a.__proto__:', a.__proto__); //{constructor: ƒ}
    console.log('a.prototype:', a.prototype); //undefined  //没有这个属性 
    
    console.log('people构造函数:', people());  //空  因为没return
    console.log('people.prototype:', people.prototype); // {constructor: ƒ}
    console.log('people.__proto__:', people.__proto__); // ƒ () { [native code] } 
    

    为什么要把属性和方法 放 原型对象上

    下面的示例可以看出,100个实例对象,它们的job都是一样的,放到自己的对象空间上,浪费大量内存空间
    所以把相同的属性方法放到原型对象上,这样就节约内存空间

    function people1(name, age, sex) {
        this.name = name
        this.age = age
        this.sex = sex
        this.job = () => {
            console.log(this.name + '执行job()');
        }
    }
    
    const a1 = new people1("小a", 18, "女")
    const b1 = new people1("小b", 19, "男")
    a1.job()    //小a执行job()
    b1.job()    //小b执行job()
    
    //把相同的属性方法放到原型对象上,节约内存空间也便于统一管理
    people1.prototype.walk = function () {
        console.log(this.name + '执行walk()');
    }
    a1.walk()    //小a执行walk()
    b1.walk()    //小b执行walk()
    
    image.png

    如何访问 原型对象空间中属性和方法?

    实例对象 访问 原型对象空间
    每一个实例都有默认的 __proto__属性,它指向 构造函数的 原型对象空间

    console.log('a.__proto__:', a.__proto__); //{constructor: ƒ}  //原型对象空间
    

    构造函数 访问 原型对象空间
    可以直接通过 构造函数.prototype 对象属性来访问原型对象空间上的属性和方法

    console.log('people.prototype:', people.prototype); // {constructor: ƒ}
    

    增加或修改原型对象的属性或方法后,所有的实例对象立即可以访问到(但创建实例后再覆盖原型除外)

    people.prototype.say = function () {
        return 'people.say方法'
    }
    console.log('people.prototype.say()', people.prototype.say()) //people.say方法
    console.log('a.say():', a.say());   //a.say(): people.say方法
    
    // 覆盖原型对象的属性或方法后,所有的实例对象不能访问
    people.prototype.run = function () {
        return 'people.run方法'
    }
    const c = new people("小c", 20, "男")
    console.log('c.run()-1:', c.run()); //c.run()-2: people.run方法
    console.log('是否相等1:', c.__proto__ === people.prototype); //true
    
    people.prototype = {
        run: function () {
            return 'people.run 覆盖后的方法'
        }
    }
    //先实例 再覆盖原型,是访问不到新的,所以仍然是之前的原型
    console.log('c.run()-2:', c.run()); //c.run()-2: people.run方法
    //因为实例中的__proto__指向的是原有地址,而构造函数的prototype 已经指向别新的地址
    //所以二者是不同的,可以看见,判断是否相等,上面是true,这里是false
    console.log('是否相等2:', c.__proto__ === people.prototype); //false
    
    const d = new people("小d", 21, "女")
    console.log('d.run()-1:', d.run()); //d.run()-1: people.run 覆盖后的方法
    console.log('是否相等3:', d.__proto__ === people.prototype); //true
    
    image.png

    实例对象访问属性和方法,访问顺序是如何的?

    实例对象 访问属性和方法,首先从 自身实例对象空间 中查找。如果找到该属性和方法,就停止查找,表示找到了;
    如果没有找到,就继续在该实例的原型对象空间中 去查找该属性和方法

    console.log(a.say()); //先从 实例的对象空间中 查找,找不到然后到原型对象空间中 查找
    

    相关文章

      网友评论

          本文标题:javascript 原型

          本文链接:https://www.haomeiwen.com/subject/ydsbrrtx.html