zoukankan      html  css  js  c++  java
  • 关于prototype

       protype是个很有趣的属性,它是“类”所持有的属性。在javascript里原生提供的一些内置类,其本质也是“类”,内置类提供的方法我们也可以通过prototype来覆盖掉,这是件很有趣的事情。例如:

    =========================================

    var str = str2 = "ab,cd,ef,g";
    var arr = str.split(",");
    String.prototype.split = function(a){
       return "hello,you input: " + a;
    }
    String.prototype.length = 200;
    var arr2 = str2.split(",");
    alert(str.length);
    alert(arr);
    alert(arr2);
    Array.prototype.toString = function(){
    return "12345";
    }
    alert(arr);

    =========================================

    猜猜看,会依次弹出什么?“10”,“ab,cd,ef,g”,“hello,you input: ,”,“12345”。呵呵,看来属性没办法覆盖,第一个没弹出“200”,但方法可以覆盖,不论是String类的split方法,还是Array类的toString方法,都被我们覆盖掉了。

    当然,覆盖内置类提供的方法这种操作绝大部分时候都是不好的,通常情况下,我们更多的是为内置类提供更多的方法,让程序更好用,例如:

    ==========================================

    var arr = ["a","b","c"];
    var str = arr.join("-");
    alert(str);
    Array.prototype.join2 = function(a){
    return this.join("^^^"+a+"^^^");
    }
    str = arr.join2("-");
    alert(str);

    ==========================================

    我们给内置类添加一个join2方法,让它在join数组的时候,能做更多我们自定义的事。因为修改的是内置类的原型,所以js中所有的原生数据都直接获得了新的方法,这是种很方便的功能。但这样的方法其实并不推荐,它会对原生内置类的原型造成“污染”,可能会出现奇怪的问题,特别是多人合作的时候,或者引入第三方js库的时候,出现一些奇怪的bug,查都不好查。我们更推荐的方法是定义一个新的类,然后把所有需要扩展的功能放到这个新的类里去,通过这个新的类来完成功能,而不是直接修改原型。如:

    ===========================================

    var arr = ["a","b","c"];
    var str = arr.join("-");
    alert(str);
    arrayManager = {
       join : function(oarr,ostr){
       return oarr.join("^^^"+ostr+"^^^");
       }
    }
    str = arrayManager.join(arr,"-");
    alert(str);

    ===========================================

    prototype是什么意思呢?它表示“原型”,简单地说,js中的类是分两级来实现的,一级是“原型级”,它比较底层,另一级是“实例级”,实例级的优先级比原型级高,如果new一个类,调用方法的时候,先优先在实例级去查找有无这个方法,如果没有,才会去原型中找。实例级在分配内存时会为每个实例分配一个,而原型级只会在内存中分配一个,通过传址的形式传给每个类的实例。所以为了节约内存,我们更推荐写类的时候将方法通过prototype的方式写出来,而不要写在function里,例如:

    =========================================

    //不推荐的写法

    function Dog(){

        this.name = "WangCai";

         this.call = function(){

            alert("wang wang");

        }

    }             

    //推荐的写法              

    function Dog(){

         this.name = "WangCai";

    }

    Dog.prototype = {

         call : function(){

              alert("wang wang");

         }

    }                                 

    =========================================

    正因为prototype是通过传址的方式供各实例调用的,所以如果对prototype进行了修改,无需重新再new一遍,实例的方法就已经更改了:

    =========================================

    function Dog(name){
       this.name = name;
    }
    Dog.prototype.call = function(){
    alert("I'm "+this.name);
    }
    var myDog = new Dog("WangCai");
    myDog.call();
    Dog.prototype.call = function(){
    alert("wang wang wang wang wang");
    }
    myDog.call();

    function Cat(name){
       this.name = name;
       this.call = function(){
       alert("I'm "+this.name);
       }
    }
    var myCat = new Cat("Mimi");
    myCat.call();
    Cat.prototype.call = function(){
    alert("miao miao miao miao miao");
    }
    myCat.call();

    =========================================

    myDog第一次call的时候,弹的是I'm WangCai,第二次就是wang wang wang wang wang了 ;myCat两次都弹的是I'm Mimi。

    正是因为prototype的这种特性,所以open api的系统里,因为会支持第三方开发,为了防止第三方恶意覆盖掉javascript内置类的方法,都会封装一套接口给第三方使用,以阻止它们访问原生内置类的原型。

  • 相关阅读:
    python的继承、封装、多态 --面向对象的特征
    ab压测工具简介
    dotnet core Console事件处理机制
    屹立千年,只为你一个回眸
    Derivative of the Sigmoid function
    Merge Overlapping Intervals
    Array of products
    Longest Peak
    javascript事件的注册方式总结
    纯css实现圆柱体-超简单!
  • 原文地址:https://www.cnblogs.com/cly84920/p/4426921.html
Copyright © 2011-2022 走看看