最新公告
  • 欢迎您光临起源地模板网,本站秉承服务宗旨 履行“站长”责任,销售只是起点 服务永无止境!立即加入钻石VIP
  • 全面解析JavaScript中的构造函数、原型prototype、原型链

    正文概述 掘金(谷底飞龙)   2021-03-27   675

    构造函数

    什么是构造函数?

    我们用一个事例来说说,如何用构造函数来创建一个对象。分两步: 1、定义一个构造函数(可包含属性和方法) 2、通过new调用构造函数创建实例

    // 定义构造函数
    function Person(name){
      // 属性
      this.name = name;
      // 方法
      this.getAge = function() {
        return 18;
      }
    }
    // 通过 new 调用函数创建实例对象
    var P = new Person('谷底飞龙')
    console.log(`my name is ${P.name}, my age is ${P.getAge()}`)
    

    通过上面的例子,我们会发现通过new创建的对象可以访问构造函数内部this指向的属性和方法。

    new 调用构造函数发生了什么?

    调用new Person('谷底飞龙')的执行过程,经历4个阶段:

    var obj  ={};
    obj.__proto__ = Person.prototype;
    Person.call(obj);
    return obj;
    
    • 1、创建新的空对象obj
    • 2、将构造函数Person的原型prototype赋值给创建的新对象obj的__proto__,这是最关键的一步,具体细节将在下文描述。
    • 3、通过call将新对象obj与构造函数内部的this进行硬绑定(可参考call和apply的原理及区别),因此,新对象obj能访问到函数内部this的属性和方法。
    • 4、返回一个对象(默认返回this)obj;

    Symbol 是不是构造函数?

    判断是否是构造函数,直接用new来调用执行试试

    new Symbol();
    

    执行后,会发现报错Uncaught TypeError: Symbol is not a constructor。因此,Symbol不支持使用new调用,所以不是构造函数,属于基本数据类型。

    我们直接使用Symbol()试试,会打印出Symbol()

    var sym = Symbol()
    console.log(sym)
    

    因此,Symbol虽然是基本数据类型,但是可以通过Symbol()来生成实例,且我们会发现实例symconstructor属性值,值为ƒ Symbol() { [native code] }。这里的constructor属性值哪里来的呢?其实是Symbol原型Symbol.prototype.constructor上的,默认是Symbol()函数。

    constructor 属性是否只读?

    • 1、引用类型的constructor属性是可以修改的
    案例正在补充中
    
    • 2、基本数据类型numberstringboolSymbol等有constructor属性的,constructor属性是只读的。我们来运行代码试试:
    let a = 1;
    console.log(a.constructor);//ƒ Number() { [native code] }
    console.log("谷底飞龙".constructor);//ƒ String() { [native code] }
    console.log(true.constructor);//ƒ Boolean() { [native code] }
    console.log(Symbol().constructor);//ƒ Symbol() { [native code] }
    
    • 3、基本数据类型nullundefined是没有constructor属性的
    console.log(null.constructor);//Uncaught TypeError: Cannot read property 'constructor' of null
    console.log(undefined.constructor);//Uncaught TypeError: Cannot read property 'constructor' of undefined
    

    原型

    什么是原型 prototype?

    因此,给已存在的构造器添加属性和方法,需要通过原型来添加。我们先来试试不通过原型来添加属性,比如给下面的构造器 Person 增加新属性 weight

    // 定义构造函数
    function Person(name){
      // 属性
      this.name = name;
      // 方法
      this.getAge = function() {
        return 18;
      }
    }
    // 通过new调用函数创建实例对象
    var P = new Person('谷底飞龙');
    
    // 给 Person 增加新属性 weight
    Person.weight = 65;
    console.log(`my weight is ${P.weight}`)
    

    添加属性失败,会打印出my weight is undefined。如果要给构造器添加属性和方法,可以通过构造函数的原型 prototype来添加,如下:

    // 定义构造函数
    function Person(name){
      // 属性
      this.name = name;
      // 方法
      this.getAge = function() {
        return 18;
      }
    }
    // 通过 new 调用函数创建实例对象
    var P = new Person('谷底飞龙');
    
    // 给 Person 增加新属性 weight 和方法 getHeight
    Person.prototype.weight = 65;
    Person.prototype.getHeight = function(){
       return 165;
    };
    console.log(`my weight is ${P.weight}, my height is ${P.getHeight()}`)
    

    通过构造函数的原型可成功添加属性weight和方法 getHeight(), 打印出my weight is 65, my height is 165

    prototype、[[Prototype]]和__proto__的区别?

    从前面讲到的new调用构造函数的执行过程的第二步:obj.__proto__ = Person.prototype,我们可以看出

    • 1、原型prototype是构造函数的属性,__proto__是 new 生成的对象的属性
    • 2、构造函数的原型 prototype 和其对象的 __proto__是赋值关系,因此指向同一个对象。如下面的例子,会打印出true
    // 定义构造函数
    function Person(name){
      // 属性
      this.name = name;
      // 方法
      this.getAge = function() {
        return 18;
      }
    }
    // 通过new调用函数创建实例对象
    var P = new Person('谷底飞龙')
    // 对象的 __proto__ 和构造函数的原型 prototype 指向同一个对象
    console.log(P.__proto__ === Person.prototype)
    
    • 3、[[Prototype]]是对象的内部属性,指向它的构造函数的原型prototype,外部无法直接访问,可以通过__proto__来访问内部属性[[Prototype]],值得注意的是,__proto__属性并非ECMAScript标准推荐使用的属性,并且是作为弃用的属性。

    • 4、内部属性[[Prototype]]无法直接在代码中使用,要用函数Object.getPrototypeOf来获取它的值,用函数Object.setPrototypeOf来改变它的值。想了解的的更详细,可以看看这篇文章 Javascript:内部属性[[Prototype]]

    原型链

    什么是原型链?

    我们来看个例子

    function Person(name){
      this.name = name;
    }
    var P = new Person('谷底飞龙')
    // 打印对象
    console.log(P)
    

    打印出对象P,如下: 全面解析JavaScript中的构造函数、原型prototype、原型链 我们可以看到,对象P有一个原型对象__proto__,P的原型对象__proto__有两个属性constructor和自己的原型对象__proto__,依次下去,最终指向null。这个案例中的原型链关系:P.__proto__ => P.__proto__.__proto__ => null

    原型链继承

    instanceof 原理及实现

    运作机制及属性遮蔽

    参考文档

    • 深入理解js构造函数
    • 重新认识构造函数、原型和原型链
    • JavaScript prototype(原型对象)
    • 一篇文章看懂_proto_和prototype的关系及区别
    • Javascript:内部属性[[Prototype]]

    起源地下载网 » 全面解析JavaScript中的构造函数、原型prototype、原型链

    常见问题FAQ

    免费下载或者VIP会员专享资源能否直接商用?
    本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
    提示下载完但解压或打开不了?
    最常见的情况是下载不完整: 可对比下载完压缩包的与网盘上的容量,若小于网盘提示的容量则是这个原因。这是浏览器下载的bug,建议用百度网盘软件或迅雷下载。若排除这种情况,可在对应资源底部留言,或 联络我们.。
    找不到素材资源介绍文章里的示例图片?
    对于PPT,KEY,Mockups,APP,网页模版等类型的素材,文章内用于介绍的图片通常并不包含在对应可供下载素材包内。这些相关商业图片需另外购买,且本站不负责(也没有办法)找到出处。 同样地一些字体文件也是这种情况,但部分素材会在素材包内有一份字体下载链接清单。
    模板不会安装或需要功能定制以及二次开发?
    请QQ联系我们

    发表评论

    还没有评论,快来抢沙发吧!

    如需帝国cms功能定制以及二次开发请联系我们

    联系作者

    请选择支付方式

    ×
    迅虎支付宝
    迅虎微信
    支付宝当面付
    余额支付
    ×
    微信扫码支付 0 元