原型链

作者: 泡杯感冒灵 | 来源:发表于2020-07-02 22:57 被阅读0次
    创建对象的几种方式
    • 对象字面量
            var obj1 = {
                name:'李思安',
                age:20,
                sayHi:function(){
                    alert('hi')
                }
            }
    
    • 通过new操作符+Object类
            var obj2 = new Object();
            obj2.name = '王小二',
            obj2.age = 25,
            obj2.sayName = function(){
                alert(this.name)
            }
    

    以上两种方式在使用同一接口创建多个对象时,会产生大量重复代码,为了解决此问题,工厂模式被开发

    • 工厂模式
            function createPerson(name,age) {
                var o = new Object();
                o.name = name;
                o.age = age;
                o.sayName = function(){
                    alert(this.name)
                }
                return o
            }
            var obj3 = createPerson('夏雨',30);
            // instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出
            console.log(obj3 instanceof Object)  // true
    

    工厂模式解决了重复实例化多个对象的问题,但是没有解决对象识别的问题(工厂模式无法识别对象的类型,因为都是Object,不像Date,Array等,因此出现了构造函数模式)

    • 构造函数
            // 构造函数模式
            function Person(name,age) {
                this.name = name;
                this.age = age;
                this.sayName = function(){
                    alert(this.name);
                }
            }
    
            var obj4 = new Person('夏雪',28);
            console.log(obj4 instanceof Object)  // true
            console.log(obj4 instanceof Person)  // true
    

    对比工厂模式有一下不同之处

    1. 没有显示的创建对象
    2. 直接将属性和方法赋值给了this 对象
    3. 没有return语句

    以此方法调用构造函数的步骤:

    1. 创建一个新对象
    2. 将构造函数的作用域赋给新对象(将this指向这个新对象)
    3. 执行构造函数代码(为这个新对象添加属性)
    4. 返回新对象

    可以看出,构造函数知道自己从哪里来(通过 instanceof 可以看出其既是Object的实例,又是Person的实例)
    构造函数也有其缺陷,每个实例都包含不同的Function实例(函数也是对象),这些函数实例做的都是同样的事情,但是却都是单独的一个函数,因此产生了原型模式

    • 原型模式
            // 原型模式
            function Person(){}
            Person.prototype.name = '夏天';
            Person.prototype.age = 35;
            Person.prototype.sayName = function(){
                alert(this.name)
            }
            var obj5 = new Person()
            console.log(obj5.name,obj5.age)  // 夏天 35
    
            var obj6 = new Person()
            obj6.name = '夏冰雹';
            obj6.sayName = function(){
                alert('hi' + this.name)
            }
            console.log(obj6.name);  // "夏冰雹"
            console.log(obj6.age);  // 35
            console.log(obj6.sayName());  // hi 夏冰雹
    
    

    原型模式的好处是所有对象实例共享它的属性和方法(即所谓的共有属性),此外还可以像obj6那样设置自己的属性和方法,即私有属性,从而覆盖原型对象上的同名属性或方法

    • 混合模式(构造函数模式+原型模式)
      构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性
            function Person(name,age) {
                this.name = name;
                this.age = age;
            }
    
            Person.prototype = {
                constructor: Person,
                sayName:function(){
                    alert(this.name)
                }
            }
    
            var obj7 = new Person('逍遥',18);
            console.log(obj7.sayName()) // 逍遥
    
            var obj8 = new Person('灵儿', 18);
            console.log(obj8.sayName())  //灵儿
    

    可以看出,混合模式共享着对相同方法的引用,又保证了每个实例有自己的私有属性,最大限度的节省了内容

    需要注意的一些概念
    • 任何函数都可以用来当构造函数(通过new运算符),不用new就是一个普通函数,总之构造函数也是函数
    • 每个函数都有一个 prototype属性,这个是在声明一个函数的时候,JS自动给它加上的属性,指向该函数的原型对象,而原型对象都有constructor属性(构造器),这是一个指向prototype属性所在函数的指针
    借用网上的一张图来表示他们之间的关系
    image.png
    • 原型的概念:每一个javascript对象(除null外)创建的时候,就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型中“继承”属性。
    • 这是每个对象(除null外)都会有的属性,叫做__proto__,这个属性会指向该对象的原型。
    • 每个原型都有一个constructor属性,指向关联的构造函数。
    原型链

    从一个实例对象往上找构造这个实例的相关联的对象,然后这个关联对象再往上找,它又有创造它的上一级的原型对象,以此类型,一直到Object.prototype原型对象终止,这个链条就达到了顶端
    那么原型链是通过什么来实现这个向上找的过程呢? 就是通过prototype原型__proto__属性来完成原型链的查找

    instanceof 就是判断一个实例是否属于某种类型

    判断的原理:就是通过判断实例下的__proto__属性和它的构造函数下的的prototype属性是不是引用的同一个地址,如果是就返回true,不是就返回false

    为什么会有instanceof

    在 JavaScript 中,判断一个变量的类型尝尝会用 typeof 运算符,在使用 typeof 运算符时采用引用类型存储值会出现一个问题,无论引用的是什么类型的对象,它都返回 "object"。所以,ECMAScript 引入了另一个 Java 运算符 instanceof 来解决这个问题。

    相关文章

      网友评论

          本文标题:原型链

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