JavaScript初阶(五)-------- 原型

原型

  原型是function对象的一个属性,它定义了构造函数制造出的对象的公共祖先。通过该构造函数产生的对象,可以继承该原型的属性和方法。原型也是对象。所以我们也能对它们进行增删改查。

             function Person() { }
             Person.prototype.name = "xiaoming";
             Person.prototype.age = 10;
             Person.prototype.sex = "male";
             var person1 = new Person();

 

  

  首先我们知道person1是构造函数Person( ) 构造出来的,所以person1继承了Person的原型,看看运行结果

                                 

       我们需要特别注意一下,person1上面的属性是只读的,不能修改它原型上的属性,也不能够删除。

 


 

原型的使用

    在使用构造函数进行初始化的时候,我们往往在赋予新的函数的特征时,只是改变部分属性,而相同的部分就是重复执行,如之前的生产汽车

    function Car(color){
                this.name = "daben";
                this.size = "big";
                this.color = color;
            }
            var car1 = new Car('green");
            var car2 = new Car("red");        

 

  

 

上面我们用构造函数得出的两个新的对象car1,car2的时候,有两条语句重复执行,也就是耦合的,这时候我们就需要解耦,就要用到原型了

 

         
           Car.prototype.name = "daben";
           Car.prototype.size = "big";
           function Car(color){
                this.color = color;
            }
            var car1 = new Car('green");
            var car2 = new Car("red"); 

 

  

   原型基本的用途就是提取公有属性,共有的,重复的,能够提取出来的,放在原型上面,而私有的个性化的属性,就可以放在函数里面,每次执行就只执行个性化的。这样就减小了耦

合,大大提高了程序执行效率。总而言之,原型就是一个对象,每一个函数有且只有一个原型。

 


 

 

 

原型的继承(原型链)

    构造函数创建对象的时候,里面有一个__proto__的属性,它指向的是该函数的原型,当访问变量的时候,如果自身没有该属性,它就会寻找__proto__上面指向的该函数的原型上去

寻找,如果这个原型上面也没有,会继续沿着原型上面的proto属性继续寻找,这条链式结构,就称之为原型链,每条原型链的终点就是Object。如果,在原型链终点上面也没有找到查询的

变量就会报undefined。

 

Constructor构造器

   当我们使用构造函数构造对象时,会有一个constructor属性,例如:

           function Car(name){
                 this.name = name;
                this.size = "big";
             }
             var car1 = new Car("daben");

 

          我们再来看看运行结果 

                                                                                 

  从结果中可以看出constructor指向的是构造出这个对象的函数func Car(name)。

而当我们用自定义的方法设定原型的时候,constructor属性是没有的,例如:

         Car.prototype = {
                 name : "daben",
                 size : "big"
             }//我们用自定义的方法设定原型
             function Car(money) {
                    this.money = money;
             }
             var car2 = new Car("10w")

  结果是这样的

                    

    我们发现__proto__下面并没有constructor属性,所以我们需要手动添加constructor属性。这就是自定义原型和原生原型的区别了。

 


 

 

 

利用原型创建对象 object.create( )

  

object.create(prototype)

 

  我们传进去的必须要是原型,如果我们传的是原始值就会报错。并且在这里我们需要特别注意,null没有原型。所以如果我们传进去的是null,系统不会报错,增删改查也能操作对象,

但是这个创建的对象没有原型,就会在运行的时候出现一些问题,比如当我们用document.write打印他的时候,因为对象是不能直接打印出来的,需要隐式的调用toString,然而没有原型

就不能使用toString方法,所以此时会报错。

  只有使用Object.create的时候才能把null传进去,其他情况手动的将prototype设定为null都是不好使的。

            面试题:所有对象的终端指向object.prototype是错误的,绝大多数才是对的,因为null没有原型。

 


 

 

与this指向有关的call 和 apply

  当我们用构造函数创建对象的时候,可以使用call和apply改变构造函数里面的this指向,例如

 function Person() {
               this.name = "hj";
               this.age = 20
           }
          var obj = { };
          Person.call(obj);
          obj      // Object { name : "hj",age :20}

 

  obj本来是个空对象,但是由于call使构造函数Person里面的this指向了obj,就相当于向obj对象里面添加了属性。

  如果传入了参数,那么第一个就是this指向,后面的就是函数参数

 

    Person.call(obj , 函数参数1,函数参数2);

    Person.apply(obj,[函数参数1,函数参数2] );

 

        他们两的区别就是传入参数的形式不同,我们往往都是用apply,因为我们可以用arguments来进行不定参操作

 

     function Person(name,age){
           this.name = name ;
           this.age = age;
        }
        var obj = { };
        function test() {
            Person.apply(obj,arguments)
        }
        test('hj',20);

  

     在多人项目开发中,当我们需要使用之前写好的代码块时,直接使用apply改变this指向。利用其他的方法构建自己的方法,提高代码运行效率。

 

posted @ 2017-12-01 10:19  暮雨橙风  阅读(116)  评论(0编辑  收藏  举报