zoukankan      html  css  js  c++  java
  • 对于js的原型和原型链的理解

    一、什么是原型:

        任何对象都有一个原型对象,这个原型对象由对象的内置属性_proto_指向它的构造函数的prototype指向的对象,即任何对象都是由一个构造函数创建的,但是不是每一个对象都有prototype,只有方法才有prototype。

      

    function Person() {
     
    }
     
    var p = new Person();
     
    //方法才有prototype,普通对象无prototype
     
    console.log(Person.prototype); // Object{}
     
    console.log(p.prototype); // undifined
     
     
     
    //任何对象都是有构造函数的,Person这种方法的构造函数是Function。
     
    //备注:constructor很容易被改变,一般不用它,此处只是打印下列对象的构造函数是什么。
     
    console.log(p.constructor); //function Person(){}
     
    console.log(Person.constructor); //function Function(){}
     
    console.log({}.constructor); // function Object(){}
     
    console.log(Object.constructor); // function Function() {}
     
    console.log([].constructor); //function Array(){}

        那什么是构造函数呢?

        用function声明的都是函数,而如果直接调用的话,那么Person()就是一个普通函数,只有用函数new产生对象时,这个函数才是new出来对象的构造函数。

    二、创建对象的过程(采用new关键)

        2.1 、声明方法的过程

        首先,当我们声明一个function关键字的方法时,会为这个方法添加一个prototype属性,指向默认的原型对象,并且此prototype的constructor属性也指向方法对象。此二个属性会在创建对象时被对象的属性引用。

       

    function Hello() {
     
    }
     
    console.log(Hello.prototype); // Object {} -- > 内部的constructor 指向Hello方法
     
    console.log(Hello.prototype.constructor); // function Hello(){}

      2.2、我们如果用Hello创建一个对象h,看这个对象有什么属性。

    console.log(h.constructor); // function Hello(){}
     
    console.log(Object.getPrototypeOf(h)==Hello.prototype); // true  备注:getPrototypeOf是获取_proto_

      我们惊喜的发现,new出来的对象,它的constructor指向了方法对象,它的_proto_和prototype相等。

      即new一个对象,它的_proto_属性指向了方法的prototype属性,并且constructor指向了prototype的constructor属性。

      2.3 、创建一个对象的过程

           

    function Hehe(name) {
     
    this.name = name;
     
    }
     
    var h = new Hehe("笑你妹");
     
    //伪代码:
     
    function newObj(name){
     
    var obj = {};
     
    obj.__proto__ = Hehe.prototype;
     
    obj.constructor = Hehe.prototype.constructor;
     
    var result = Hehe.call(obj, name);
     
    return typeof result==='object'&& result!=null ? result : obj; //当无返回对象或默认时返回obj。
     
    }
     
    var hh = newObj("笑你妹");
     
    console.log(hh);
     
    console.log(h);
    //虽然hh!=h,但是可以看到这个hh就和h的结构一样了。

        过程:先创建一个空对象,设置一个_proto_指向方法的原型,设置constructor,用新对象做this指向方法,返回新对象。

    2.4、延伸

        从上面说明的过程中,我们发现只要是对象就是有构造函数来创建的,并且内部二个属性是从构造函数的prototype衍生的一个指向,而构造函数的prototype也是一个对象,那么它应该肯定也有一个构造函数,首先它是一个Object {} 对象,那么它的构造函数肯定是Object,所以就会有一个指针_proto_指向Object.prototype。最后Object.prototype因为没有_proto_,指向null,这样就构成了一个原型链。

        三、原型链

        1)什么是原型链?

        原型链的核心就是依赖对象的_proto_的指向,当自身不存在的属性时,就一层层的扒出创建对象的构造函数,直至到Object时,就没有_proto_指向了。

        2)如何分析原型链?

        因为_proto_实质找的是prototype,所以我们只要找这个链条上的构造函数的prototype。其中Object.prototype是没有_proto_属性的,它==null。

        3.1、最简单的原型链分析

       

    function Person(name){
     
    this.name = name;
     
    }
     
    var p = new Person();
     
    //p ---> Person.prototype --->Object.prototype---->null

         属性搜索原则:
         1.当访问一个对象的成员的时候,会现在自身找有没有,如果找到直接使用。
         2.如果没有找到,则去 原型链指向的对象的构造函数的prototype中找,找到直接使用,没找到就返回undifined或报错。

         3.2、原型链上属性查询的案例

         //略。。。

         3.3、原型继承

        

    //原型继承的基本案例
    function Person(name, age) {
        this.name = name;
        this.age = age;
    }
    //1.直接替换原型对象 
    var parent = {
        sayHello : function() {
            console.log("方式1:替换原型对象");
        }
    }
    Person.prototype = parent;
    var p = new Person("张三", 50);
    p.sayHello();
    //2.混入式原型继承
    console.log(".............混入式原型继承..............");
    function Student(name, age) {
        this.name = name;
        this.age = age;
    }
    var parent2 = {
        sayHello : function() {
            console.log("方式2:原型继承之混入式加载成员");
        }
    }
    for ( var k in parent2) {
        Student.prototype[k] = parent2[k];
    }
    var p = new Student("张三", 50);
    p.sayHello();
  • 相关阅读:
    KMP
    KMP算法的Next数组详解
    从头到尾彻底理解KMP
    通信协议:HTTP、TCP、UDP
    十大Intellij IDEA快捷键
    Java连接oracle数据库的两种常用方法
    Oracle 数据类型
    Oracle 数据库、实例、用户、表空间、表之间的关系
    Android中的Handler的机制与用法详解
    在Android开发中,定时执行任务的3种实现方法
  • 原文地址:https://www.cnblogs.com/plBlog/p/14025496.html
Copyright © 2011-2022 走看看