到底什么是JS原型

时间:2021-05-13 14:56:26 类型:JS/JQUERY
字号:    

  关于JS原型的解释,查看网上的资料, 大多数都看的云里雾里, 其主要原因就是, 在解释前很多都忽略了普通用户对一些专业名词、概念本身就不懂的情况,本身就晕, 里面的解释, 也是晕的, 看似都是汉字, 数数都认识, 但看结果, 还是晕糊糊,导致大家走了很多很多弯路

  一、首先在我们对JS原型进行解释的时候,我们首先要理解涉到的两个概念:构造函数、原型对象


  1. 构造函数:在script标签里面声明的那个函数(注意: 区分与JAVA,PHP,Python等后台语言不要混为一谈)

    如下


  2. <script>
                function person(name,age){
                    this.name = name;
                    this.age  = age;
                    //在这里, 整个函数就是构造函数
                }
        </script>

    2.  原型对象:在声明上面这个函数后,浏览器会自动按照一定的规则在内存中创建一个对象,这个对象就叫做原型对象

 

  3.在声明了一个函数后,这个构造函数(即声明了的函数)中会有一个属性prototype,这个属性指向的就是这个构造函数对应的原型对象;原型对象中有一个属性constructor,这个属性指向的是这个构造函数下面一张图可以很简单理解:看图会意

        protopyte.jpg

  二、使用构造函数创建对象

  此时,p1就是那个构造函数person创建出来的对象,这个对象中是没有prototype属性的,prototype属性只有在构造函数person中有,请看图!

 var p1 = new person("庄子",18);
     console.dir(p1);
     console.log("----------------------------------------");
     console.dir(person)

.jpg

 可以看出,构造函数person中有prototype属性,指向的是person对应的原型对象;

                            而p1是构造函数person创建出来的对象,它不存在prototype属性,但p1有一个__proto__属性,stu调用这个属性可以直接访问到构造函数person的原型对象(也就是说,p1的__proto__属性指向的是构造函数的原型对象),请看图

3.jpg

  从上面的代码中可以看到,创建p1对象虽然使用的是person构造函数,但是对象创建出来之后,这个p1对象其实已经与person构造函数没有任何关系了,p1对象的__proto__属性指向的是person构造函数的原型对象。

  如果使用new person()创建多个对象p1、p2、p3,则多个对象都会同时指向person构造函数的原型对象。

  我们可以手动给这个原型对象添加属性和方法,那么p1,p2,p3…这些对象就会共享这些在原型中添加的属性和方法。

  如果我们访问p1中的一个属性name,如果在p1对象中找到,则直接返回。如果p1对象中没有找到,则直接去p1对象的__proto__属性指向的原型对象中查找,如果查找到则返回。(如果原型中也没有找到,则继续向上找原型的原型—原型链)。

  如果通过p1对象添加了一个属性name,则p1对象来说就屏蔽了原型中的属性name。 换句话说:在p1中就没有办法访问到原型的属性name了。

  通过p1对象只能读取原型中的属性name的值,而不能修改原型中的属性name的值。 p1.name = “小强”; 并不是修改了原型中的值,而是在p1对象中给添加了一个属性name。

通过下面的程序来理解上面说的内容:

 function person(name,age){
                this.name = name;
                this.age  = age;
                //在这里, 整个函数就是构造函数
            }
             // 可以使用students.prototype 直接访问到原型对象
        //给students函数的原型对象中添加一个属性 name并且值是 "张三"
        person.prototype.hobby = "篮球";
        person.prototype.email = "abc@163.com";
 
        var p1 = new person("王小二",18);
        /*
            访问p1对象的属性hobby,虽然在p1对象中我们并没有明确的添加属性name,但是
            p1的__proto__属性指向的原型中有hobby属性,所以这个地方可以访问到属性hobby的值
            注意:这个时候不能通过p1对象删除hobby属性,因为只能删除在p1中删除的对象。
        */
        console.log(p1.hobby);  // 篮球
 
        var p2 = new person('王小二',19);
        console.log(p2.hobby);  // 篮球  都是从原型中找到的,所以一样。
 
        console.log(p1.hobby === p2.hobby);  // true


<