zoukankan      html  css  js  c++  java
  • JS原型与原型链

    一.普通对象与函数对象

    Javascript中,万物皆对象,但分为普通对象和函数对象,Object,Function是JS自带的函数对象。 
    下面举例说明:

    function f1(){};
    console.log(typeof f1);//输出function 函数对象
    
    var f2 = function(){};
    console.log(typeof f2);//输出function 函数对象
    
    var f3 = new Function('str','console.log(str)');
    console.log(typeof f3);//输出 function 函数对象
    
    var a1 = new f1();
    console.log(typeof a1);//输出object 普通对象
    
    var a2 = {};
    console.log(typeof a2);//输出object 普通对象
    
    var a3 = new object();
    console.log(typeof a3);//输出object 普通对象

    二.原型对象

    在JavaScript中,每当定义了一个对象(函数)时候,对象中都会包含一些预定义的属性。其中函数对象的一个属性就是原型对象prototype。普通对象无prototype属性,但是有_ prototype_属性 
    下面来说一说prototype 和_ proto _ 
    prototype:显示原型 
    _ proto _:隐式原型 
    1.显示原型和隐式原型是什么? 
    函数对象具有的一个属性是prototype,称为显示原型,这个属性是一个指针,指向原型对象。原型对象也有一个属性constructor,这个属性包含一个指针,指向原构造函数

    如上图,SuperType是一个函数,右侧的方框就是它的原型。

    对象都具有的一个属性proto称为隐式原型,对象的隐式原型指向构造该对象的构造函数的显示原型

    探究二者之间的关系

    隐式原型指向创建这个对象的函数的prototype 
    下面来探究一下三种创建对象的方法中隐式原型和显示原型的关系:

    1.通过对象字面量来创建一个对象

    var person = {
      name = "Tom";
    }

    通过对象字面量的方式创建的对象,它的隐式原型指向Object.prototype,因为person这个对象是通过new Object()函数所创建出来的 
    上面的代码相当于:

    var person = new object();
     person.name = "Tom";

    2.通过Object.create()方式创建

    先介绍一下Object.create()方式 
    1.定义: 
    Object.create()方法会使用指定 的原型对象及其属性去创建一个新的对象 
    2.语法:

    Object.create(proto, [ propertiesObject ])

    3.参数: 
    proto 
    一个对象,新创建的对象的原型。 
    propertiesObject 
    可选。该参数对象是一组属性与值,该对象的属性名称将是新创建的对象的属性名称,值是属性描述符(这些属性描述符的结构与Object.defineProperties()的第二个参数一样)。注意:该参数对象不能是 undefined,另外只有该对象中自身拥有的可枚举的属性才有效,也就是说该对象的原型链上属性是无效的 
    4.返回值: 
    返回一个新对象。在指定原型对象上添加新属性后的新对象 
    5.抛出异常: 
    如果 propertiesObject 参数不是 null 也不是对象,则抛出一个 TypeError 异常 
    举例:用Object.create实现类继承

    //Shape - superclass
    function Shape() {
      this.x = 0;
      this.y = 0;
    }
    
    Shape.prototype.move = function(x, y) {
        this.x += x;
        this.y += y;
        console.info("Shape moved.");
    };
    
    // Rectangle - subclass
    function Rectangle() {
      Shape.call(this); //call super constructor.
    }
    
    // subclass extends superclass
    Rectangle.prototype = Object.create(Shape.prototype);
    Rectangle.prototype.constructor = Rectangle;
    
    var rect = new Rectangle();
    
    console.log('Is rect an instance of Rectangle?',
      rect instanceof Rectangle); // true
    console.log('Is rect an instance of Shape?',
      rect instanceof Shape); // true
    
    rect.move(1, 1); //Outputs, "Shape moved."

    通过这种方法创建的对象的隐式原型指向proto

    通过new方式创建

    function person(name){
      this.name = name;
    }
    //创建一个构造函数的实例
    var person1 = new person();

    构造函数function person 本质是由Function构造函数创建的,它是Function 的一个实例。原型对象本质是由Object构造函数创建的。内置函数Array,Number,等也是由构造函数创建的 
    下面来探究person1的隐式原型:

    //通过new的方式
    person1.__proto__===person.prototype //true
    person.prototype.__proto__===Object.prototype //true   person.prototype也是一个对象,它是通过new Object创建得到的
    Object.__proto__===Function.prototype //true
    //内置函数
    Array.__proto__===Function.prototype //true
    Array.prototype.__proto__===Object.prototype //tr

    Function的proto指向其构造函数Function的prototype;

    Object作为一个构造函数,它是一个函数对象,所以他的proto指向Function.prototype;

    Function.prototype的proto指向其构造函数Object的prototype;

    Object.prototype的prototype指向null(尽头);

    经典图片解析: 

    其实:原型对象其实就是普通对象(Function.prototype除外,它是函数对象,但它很特殊,他没有prototype属性(前面说道函数对象都有prototype属性)。 
    举例:

    function f1(){};
     console.log(f1.prototype) //f1{}
     console.log(typeof f1. prototype) //Object
     console.log(typeof Function.prototype) // Function,这个特殊
     console.log(typeof Object.prototype) // Object
     console.log(typeof Function.prototype.prototype) //undefined

    从这句console.log(f1.prototype) //f1 {} 的输出就结果可以看出,f1.prototype就是f1的一个实例对象。就是在f1创建的时候,创建了一个它的实例对象并赋值给它的prototype 
    原型对象是用来做什么的呢?主要作用是用于继承。举个例子:

    var person = function(name){
     this.name = name;
    }
    person.prototype.getname = function(){
      return this.name;
    }
    var zjh = new person('zhangjiaahao');
    zjh.getName();//zhangjiaohao

    从这个例子可以看出,通过给person.prototype设置了一个函数对象的属性,那有person实例(例中:zjh)出来的普通对象就继承了这个属性。具体是怎么实现的继承,就要讲到下面的原型链了。

    三.原型链

    JS在创建对象(不论是普通对象还是函数对象)的时候,都有一个叫做proto的内置属性,用于指向创建它的函数对象的原型对象prototype。以上面的例子为例: 
    console.log(zjh.proto === person.prototype) //true

    同样,person.prototype对象也有proto属性,它指向创建它的函数对象(Object)的prototype

    console.log(person.prototype.proto === Object.prototype) //true

    继续,Object.prototype对象也有proto属性,但它比较特殊,为null

    console.log(Object.prototype.proto) //null

    我们把这个有proto串起来的直到Object.prototype.proto为null的链叫做原型链

  • 相关阅读:
    SQL手工注入方法
    Python + Django 网站平台搭建之- 初识 (一)
    最新版Idea2019.3.4/2020.1完美破解
    使用 Guns 自动生成 SpringBoot + LayUI 的后台管理系统
    SpringBoot+Layui后台管理系统
    国内Maven中央仓库推荐 速度最快最好的Maven仓
    git 下载失败 中断了 继续下 怎么配置参数
    mysql 创建与授权
    jboot-admin
    自动生文器
  • 原文地址:https://www.cnblogs.com/web-record/p/9662942.html
Copyright © 2011-2022 走看看