原型链

2020-07-02  本文已影响0人  泡杯感冒灵
创建对象的几种方式
        var obj1 = {
            name:'李思安',
            age:20,
            sayHi:function(){
                alert('hi')
            }
        }
        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())  //灵儿

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

需要注意的一些概念
借用网上的一张图来表示他们之间的关系
image.png
原型链

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

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

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

为什么会有instanceof

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

上一篇下一篇

猜你喜欢

热点阅读