zoukankan      html  css  js  c++  java
  • js 的constructor属性

    引用类型null typeof null // object

    所有的引用类型都是object

    constructor 属性

    定义和用法

    constructor属性返回对创建此对象的数组函数的引用

    demo1

    let test = new Array();

    console.log(test.constructor===Array)//true

    demo2

    function people(name,age){
    this.name = name;
    this.age = age;
    }
    let p1 = new people('z','18');
    document.write(p1.constructor);
    //function people(name,age){ this.name = name; this.age = age; }

    在js语言中,constructor属性时专门为function而设计的,它存在于每一个function的prototype属性中,这个constructor保存了指向function的一个引用。

    在定义一个函数时,function F(){} js内部会执行2个动作

      1 为该函数添加一个原型(prototype)属性

      2 为prototype对象额外添加一个constructor属性并且该属性保存指向函数F的一个引用

    这样当我们把函数F作为一个构造函数来创建对象的时候,对象实例内部都会自动保存一个指向其构造函数的prototype对象的一个属性__proto__

    所以我们在每一个对象实例中都可以访问构造函数的prototype所有拥有的属性和方法,就好像他们是实例自己的一样。当然该实例也有一个constructor属性了(从prototype那里获得的),每一个对象实例都可以通过constructor对象访问它的构造函数,(如下)

    let f = new F()

    console.log(f.constructor ===F)//true

    console.log(f.constructor === F.prototype.constructor)//true

    我们可以利用这个特性来完成下面的事情:

      对象的类型判断,if(f.constructor === F){//do something}

      其实constructor的出现本来就是用来进行对象类型判断的,但是constructor属性易变,不可信赖,所以我们用其他的方法进行判断,如if(f instanceof F){// do someThing}

    原型链继承,忧郁constructor存在于prototype对象上,因此我们可以结合constructor 沿着原型链找到最原始的构造函数,

    function Base(){}
    function Sub1(){}
    Sub1.prototype = new Base();
    Sub1.prototype.constructor = Sub1;
    Sub1.superclass = Base.prototype;
    //console.log(Sub1);
    //console.log(Sub1.prototype)// function Base(){}
    //console.log(Sub1.prototype.constructor)// function Sub1(){}
    //console.log(Sub1.superclass)// function Base(){}
    function Sub2(){}
    Sub2.prototype = new Sub1();
    console.log(Sub2.prototype)//function Sub1(){}
    Sub2.prototype.constructor = Sub2;
    console.log(Sub2.prototype,constructor)//function Sub1(){}
    console.log(Sub2.superclass)//undefined
    Sub2.superclass = Sub1.prototype;
    console.log(Sub2.superclass) //base{}


    console.log(Sub2.prototype.constructor);// function Sub2(){}
    console.log(Sub2.superclass.constructor);// Sub1(){}
    console.log(Sub2.superclass.constructor.superclass.constructor);//Base(){}
    上面的例子只是为了说明constructor在原型链中的作用,更实际一点的意思在于:一个子类对象可以获得其父类的所有
    属性和方法,称之为继承。
    之前说到了constructor易变,那是因为函数的prototype属性容易被更改,我们用demo说明
    function F(){
      F.prototype = {
        _name:'123',
        getName:function(){

          return this._name
        }
      
      }
    }
    let f = new F();
    console.log(f.constructor === F)//false
    怎么回事?F不是实例对象f的构造函数了嘛?当然是,只不过构造函数F的原型被开发者重写了
    这中方式将原来的prototype对象用一个对象的字面量{}来代替了,而新的对象{}只是Object
    的一个势力,视同在解析的时候并不会在{}上自动添加一个constructor属性,因为这是function
    创建是的专属操作,仅当你声明函数的时候解析器才会做此动作,然而你会发现constructor
    并不是不存在的:下面证明
    console.log(typeof f.constructor =="undefined")// false
    尽然存在那整个constructor到底是从哪里的呢?
    因为{}是创建对象的简写,所以这个{}相当于new Object(),那既然{}是Object的实例,
    自然而然他获得一个指向构造函数Object()的prototype属性的一个引用__proto__,又因为
    Object.prototype上有一个指向Object本身的constructor属性,所以可以看出这个constructor
    其实就是Object.prototype的constructor,所以
    console.log(f.constructor === Object.prototype.constructor)//true
    console.log(f.constructor === Object)//true

    一个解决办法就是手动回复他的constructor,看下面

    function F(){

      F.prototype = {

        constructor:F,

        _name:'123'

    }

    }

    这以后一切都回复正常了,constructor重新获得的构造函数的引用,我们可以再一次验证

    let f= new F();

    console.log(f.constructor === F);//true

    疑问:构造函数上怎么还有一个constructor?他是从哪儿来的?

    其实js的内建的构造函数,比如Array,RegExp,String,Number,

    Object,Function都是有一个constructor的,

    console.log(typeof Array.constructor != 'undefined')//true

    这个东西不要搞混了,这个跟prototype上的constructor不是同一个对象,

    他们是共存的。

    console.log(Array.prototype.constructor === Array);//true

    不过这件事也好理解,因为构造函数也是函数,是函数就说明它就是Function构造函数的实例对象,自然它内部也有一个指向Function.prototype的内部引用的__proto__,因此我们很用以得出结论,这个constructor其实就是Function构造函数的引用

    console.log(Array.constructor === Function)//true

    console.log(Fuinctuon.constructor === Function)//true

  • 相关阅读:
    Java weak reference
    Java 代理模式
    Eclipse 代码自动提示
    Eclipse 设置默认编码为Utf-8
    MyBatis 作用域(Scope)和生命周期
    MyBatis 命名空间与命名解析
    Java 泛型 介绍
    【总结】过去的风口让很多人改变了阶层,我们90后的下一个风口会是什么?
    【前端】js截取or分割字符串的常见方法
    基于react/vue的移动端终极适配方案vw单位(更新css-modules配置)
  • 原文地址:https://www.cnblogs.com/lieaiwen/p/10219783.html
Copyright © 2011-2022 走看看