• js原型与原型链浅析


    原型 和原型链

    什么是原型链

    本质:原型链是用来实现js对象继承的方式
    简单理解就是原型组成的链,对象的__proto__它的是原型,而原型也是一个对象,也有__proto__属性,原型的__proto__又是原型的原型,就这样可以一直通过__proto__想上找,这就是原型链,当向上找找到Object的原型的时候,这条原型链就算到头了。

    原型与原型链的几个要点
    • 每一个函数都有一个prototype属性 和 一个 __proto__属性。
    • 每一个对象都有一个__proto__属性 。
    • (除null)所有的对象都是由构造函数创建的。
    • 对象的__proto__ === 该对象的构造函数的prototype ( [].proto === Array.prototype)
    • 对象的__proto__ 也是一个对象,所以对象的__proto__的__proto__ === Object.prototype
    • null位于原型链最顶层
    • Function.proto === Function.prototype。 这是一个先有蛋还是先有鸡的问题
    • null 没有__proto__ 和 prototype
    • 所有原型链属性传递方向 (某个属性在本对象中找不到时候,会到原型链上去找): 先找对象 本身属性 =》构造函数的prototype中属性 =》Object.prototype中的属性=》null (结束)
    例子:
    function Person(){
        this.name = name;
        this.age = age;
    }
    Person.prototype.talk = function(){
        console.log("hello");
    }
    let ming = new Person("ming",24);//ming === {name:"ming",age:24}
    ming.talk(); // ming中没有talk这个属性,就会通过__proto__到到原型链中去找,ming.__proto__ ===  Person.prototype。
    //由于ming.__proto__也就是 Person.prototype 也是一个对象,所以  ming.__proto__.__proto__ ===  Object.prototype。(如果ming.__proto__中没有找到talk属性会继续向上找ming.__proto__.__proto__ ,直到找到最顶层null)
    
    原型链的应用

    通过一个构造函数创建出来的多个实例,如果都要添加一个方法,给每个实例去添加并不是一个明智的选择。这时就该用上原型了。

    在实例的原型上添加一个方法,这个原型的所有实例便都有了这个方法。
    例子:给所有的function 添加一个 before属性 和 after属性

    Function.prototype.before = function(beforeFn){
    	let functionObj = this;
    	return function (){
    		beforeFn.apply(this,arguments);
    		functionObj.apply(this,arguments);
    	}
    }
    Function.prototype.after = function(afterFn){
    	let functionObj = this;
    	return function (){
    		functionObj.apply(this,arguments);
    		afterFn();
    	}
    }
    function test(){
    	console.log('this is a test function!');
    }
    let test1 = test.before(function(){
    	console.log(arguments);
    	console.log('before');
    }).after(()=>{
    	console.log('after');
    });
    test1();
    
    思考:为什么通用方法写入原型链中比直接写在构造函数中更好?
    //例子1
    function Animal (){
        this.speak = function(){}//第一种,直接将方法写入构造函数中
    }
    Animal.prototype.speak = function(){};//第二种将方法写到原型链中
    let dog1 = new Animal();
    let dog2 = new Animal();
    console.log (dog1.speak === dog2.speak) //第一种,返回false,第二种返回true
    

    总结:假如将方法写入构造函数中,每一次实例化都会去创建这样一个功能完全相同的函数,会非常耗费内存,而写入原型链中只会创建一次,所以建议通常情况下将实例方法写到原型链中。

    一个原型与原型链的图解

  • 相关阅读:
    IPSec (一)
    python 面向过程和面向对象
    一键修改 yum 源为 aliyun 阿里源 Shell 脚本
    第11组Alpha冲刺(6/6)
    第11组Alpha冲刺(5/6)
    第11组 Alpha冲刺(4/6)
    第11组Alpha冲刺(3/6)
    第11组 Alpha冲刺 (2/6)
    第11组 Alpha冲刺 (1/6)
    第11组(73)需求分析报告
  • 原文地址:https://www.cnblogs.com/honkerzh/p/10839555.html
Copyright © 2020-2023  润新知