js中的原型与原型链

面向对象、面向过程和构造函数

面向对象:把数据和对数据的操作方法放在一起,构成一个相互依存的整体,对象和对象之间可以通信,程序流程由用户在使用中确定。
面向过程:自顶向下执行,程序结构按照功能划分成各个基本的模块,程序的流程在写程序时已经确定。
在js中创建对象有两种办法,对象字面量和使用new表达式,在使用new表达式创建对象时就使用到了构造函数。

一个函数作为构造函数和普通函数返回值是不同的。

  • 当return的内容是引用类型时
 function Test(){
            this.a = 10;
            return function(){
                return 1;
            }
            // return 1;
        }
        var b = Test();
        console.log(b);
        console.log(typeof(b));
        
        var c = new Test();
        console.log(c);
        console.log(typeof(c));

运行结果如下
在这里插入图片描述
c作为Test构造函数的实例,this.a丢失,被返回值所取代。

  • 当return的内容是值或者没有return时
 function Test(){
            this.a = 10;
            // return function(){
            //     return 1;
            // }
            return 1;
        }
        var b = Test();
        console.log(b);
        console.log(typeof(b));
        
        var c = new Test();
        console.log(c);
        console.log(typeof(c));

运行结果如下
在这里插入图片描述
这时构造函数成功的构造了c实例。

new关键字做了什么

  • 在构造函数内创建了一个临时的对象
  • 将构造函数内临时对象的__proto__属性和构造函数的原型进行绑定
  • 将临时对象的作用域赋给真正的对象即改变this指针的指向,并将创建好的对象返回
  • 将所有构造函数的原型统一命名为prototype

原型和原型链

我个人觉得最绕的地方,首先名词多,然后互相之间的关系歪七扭八的。接下来我用我能理解的方法解释下这个问题。
这个问题的产生是为了实现原型上属性和方法的继承,提高代码的复用率。构造函数就相当于模具,但是关于这个模具具体的一些属性,比如大小,材质之类的并没有直接写在模具里,而是把这些属性和方法放在了原型(prototype)里,在构造函数内部通过__proto__属性将两者绑定了。在js万物皆对象的思想下,__proto__属性是每个对象都有的,包括原型。
ps:因为绝大部分浏览器都支持__proto__属性,所以它才被加入了 ES6 里(ES5 部分浏览器也支持,但还不是标准)。

然后在有了模具的前提下,就可以来创造实例了,但是实例不光可以继承属性和方法,还可以有自己的属性和方法。就像父子的关系一样,虽然相似但也有不同。而原型中也有一个属性指向创造出来的实例,就是构造器(constructor)属性,构造器(constructor,包括: Object;Function;Array;Date;String等函数)才有prototype属性,对象(除Object外)都拥有__proto__。

所以在通过构造函数创造实例的过程中,构造函数只是一个桥梁,将实例通过原型创造出来了而已,在实例被创造出来的时候,构造函数中的this指针就已经指向被创造的实例,实例的__proto__就指向了实例的原型,而构造函数就退出历史舞台。而原型链指的是,在找寻某个实例的方法和属性的过程中,先在自身查找,然后通过实例的__proto__找到实例的原型,实例的原型再通过实例的原型的__proto__找到了Object的原型,Object的原型再通过Object的原型的__proto__找到Object的原型的__proto__的原型为null,就到顶了。所以说原型链是通过__proto__而不是原型,而且这个连接存在在实例和原型之间,和构造函数没有什么关系。

以下是引用

所有函数对象proto都指向 Function.prototype,它是一个空函数(Empty function)。

1、Object.proto === Function.prototype // true
Object 是函数对象,是通过new Function()创建的,所以Object.__proto__指向Function.prototype。
2、Function.proto === Function.prototype // true
Function 也是对象函数,也是通过new Function()创建,所以Function.__proto__指向Function.prototype
3、Function.prototype.proto === Object.prototype //true
Function.prototype是个函数对象,理论上他的__proto__应该指向 Function.prototype,就是他自己,自己指向自己,没有意义。
JS一直强调万物皆对象,函数对象也是对象,给他认个祖宗,指向Object.prototype。Object.prototype.proto === null,保证原型链能够正常结束。

在这里插入图片描述

在这里插入图片描述

参考文章

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值