• 【JavaScript】JS_Object跟Function的区别


    JS_Object和Function的区别

    我们本次的解释,主要通过下图

    Javascript的Prototype,Function,Object,__proto__关系示意图

    粗看该图,估计你不一定能看明白。不过接下来让我逐行向你解释。

    • 最左侧:意思是,有两个对象f1和f2,他们是通过new Foo()出来的。
    • 中间:Foo()就是最左侧用到的Foo()
    • 最右侧:表示,函数Foo()的prototype属性!
    1、__proto__的虚线:该条线表示通过f1.__proto__可以访问到Foo.prototype,其实两者是等价的。
    2、constructor实现:表示通过Foo.prototype.constructor可以找到Foo
    function Foo() {
    }
    var f1 = new Foo();
    alert(f1.__proto__ == Foo.prototype);
    ?function Object(){[native code]}//Javascript自带,不是自定义的,可以近似认为是基类

    function Function(){[native code]}//Javascript自带,不是自定义的,可以近似认为是基类

    ?

    这里的这两个function,分别走两个方向,
    Object作为了众多object(实例,new出来的)的基类型
    Function作为众多function(主要是那些function出来的,就是定义出来的函数)的基类型

    ?

    在开始下面更细致的解释先,我们约定一些内容,Object代表这里所说的Object,object代表实例对象
    ,Function代表这里说的Function,function是关键字。对于Object与object的区别很好理解,一个是function,一个是new出来。

    ?

    现在让我们思考两个问题:
    第一个,当我们扩展Object原型时,new出来的Function,是否会被扩展?
    第二个,当我们扩展Function原型时,由于Object也是个Function,那么其实例object是否会被扩展

    ?

    先看第一个问题.eg.

    ?

    Object.prototype.test4extend="123";//扩展Object的原型 
    
     document.write("Function:"+Function.test4extend);//在Function中出现了test4extend属性
     document.write("<br>")
     document.write("Object:"+Object.test4extend);//在Object中出现了test4extend属性,此时Object还是个Function
     document.write("<br>")
     var obj=new Object;
     document.write("Object instance:"+obj.test4extend);//在obj中扩展了test4extend,此时的obj是object
     document.write("<br>")
     function Foo()
     {
    
     }
    
     var foo = new Foo;
     document.write("foo object:"+foo.test4extend);//foo对象上扩展上了test4extend属性
     document.write("<br>")
     document.write("Foo Function:"+Foo.test4extend);//函数上也扩展上了test4extend属性
     document.write("<br>")
    
    console.log("Object", Object);
    console.log("Function", Function);
    ?注释已经写得很清晰了,通过以上几点我们很容易发现以下几点:

    ?

    1、Object扩展了所有的object(obj,foo),与object扩展自Object是相符的。在这里更加验证了。
    2、Object扩展了Function,这点说明Function扩展自Object,说明Object比Function更底层些。
    3、Object扩展了自身的属性,即Object.test4extend也是可以的。
    这点说明,Object扩展了Function,又因为Object本身又是通过function定义出来的,所以会受到Function影响,所以,反过来Function又扩展了Object。

    接下来看看第二个问题

      Function.prototype.test4extend="123";//扩展Function的原型
      document.write("Function:"+Function.test4extend);//在Function中出现了test4extend属性
      document.write("<br>")
      document.write("Object:"+Object.test4extend);//在Object中出现了test4extend属性,注意此时Object是个Function
      document.write("<br>") var obj=new Object; document.write("Object
      instance:"+obj.test4extend);//在obj中没有扩展上test4extend,此时的obj是object
      document.write("<br>") function Foo() { }
      
      var foo = new Foo; document.write("foo
      object:"+foo.test4extend);//foo对象上没有扩展上test4extend document.write("<br>")
      document.write("Foo Function:"+Foo.test4extend);//Function扩展上了test4extend属性
      document.write("<br>")

    ??

    ?这说明Function只管没有被实例化得,被实例化的,他是没有办法管的。与Object不同,Object是无论是否实例化都管的。

    接下来解释这个图:

    先看最左侧的__proto__虚线,表示Foo.__proto__相当于Function.prototype,这里和Object情况差不多,只是属性一致而已,并不是指真正的那个Function

    中间的下部的__proto__虚线,代表Function.__proto__等于Function.prototype,这里可是真的就是,和前面的相当于不同。

    alert(Function.__proto__===Function.prototype);//true

    ?右侧左上的__proto__虚线,代表Object.__proto__等于Function.prototype,这里可是真的就是,和前面的相当于不同。

    alert(Object.__proto__===Function.prototype);//true

    ?

    ?右侧右上的__proto__虚线,代表Function.prototype.__proto__相当于Object.prototype,只是属性一致而已,并不是真的。

    先让我们总结下__proto__和prototype的区别和关系。

    区别:从实际效果上来说,可以认为__proto__是用来扩展Function的,扩展出来的函数,可以直接调用,不需要new出对象才能用,同时对象是不会扩展通过__proto__扩展的方法或属性的

    function Foo() {
    
    }
    Foo.__proto__.test = "__proto__ test property found";// 通过__proto__扩展
    Foo.__proto__.addextend = function() {
    	document.write("Foo add extend by __proto__");
    	document.write("<br>");
    }
    Foo.addextend();// 可以执行
    var foo = new Foo;
    document.write("Foo:" + Foo.test);// 可以访问
    document.write("<br>");
    document.write(foo.addextend);// 未定义
    document.write("<br>");
    document.write("Foo instance:" + foo.test);// 未定义
    document.write("<br>");
    ?

    ?

    ?对于prototype来说,它是针对对象的,也就是Function是无法使用的,只有new出来的才能有效

    ?

    function Foo()
    {
    
    }
    Foo.prototype.test="prototype test property found";
    Foo.prototype.addextend=function(){
    	document.write("Foo add extend by prototype");
    	document.write("<br>");}
    
    document.write(Foo.addextend());//未定义
    document.write("<br>")
    
    var foo=new Foo;
    document.write("Foo:"+Foo.test);//无法访问
    document.write("<br>")
    foo.addextend();//可以执行
    document.write("foo instance:"+foo.test);//找到了
    document.write("<br>"
    ?

    ?

    • ?在Object中__proto__是Function的prototype是Object。
    • 在Function中__proto__是Function的prototype也是Object。
    • 现在让我们再来结合第三行的图看一看。有如下关系。
      Function.__proto__就是(===)Function.prototype
      Object.__proto__就是(===)Function.prototype
    • Function的__proto__和prototype就是一个,扩展任何一个都是相同的效果。Object的__proto__就是Function.prototype。当我们扩展Object.__proto__时,就相当于扩展了Function.prototype和__proto__,反之亦然。
    Object.__proto__.test4extend="123";//扩展Object的原型 
    ?
    alert("Function:"+Function.test4extend);//在Function中出现了test4extend属性
    ?
    alert("Object:"+Object.test4extend);//在Object中出现了test4extend属性,此时Object还是个Function
    ?
    var obj=new Object;
    alert("Object instance:"+obj.test4extend);//未定义
    ?
    function Foo()
    {
    ?
    }
    ?
    var foo = new Foo;
    alert("foo object:"+foo.test4extend);//未定义
    ?
    alert("Function:"+Foo.test4extend);//函数上也扩展上了test4extend属性
    ?

    ?【总结】

    Function扩展自Object,但是Function对Object又有影响,这是通过Object.__proto__就是(===)Function.prototype建立的联系。记住这个联系后,我们还要记住__proto__和prototype的区别,前者扩展的只可以被Function直接调用,后者扩展的只可以通过其实例调用。另外,还要注意__proto__和prototype的链的概念,这是因为,他们可以互相关联,访问到Function或Ojbect的内容。
     
  • 相关阅读:
    密码保护
    实现搜索功能
    完成个人中心—导航标签
    个人中心标签页导航
    评论列表显示及排序,个人中心显示
    完成评论功能
    从首页问答标题到问答详情页
    首页列表显示全部问答,完成问答详情页布局
    Android基础学习:Android环境搭建
    liunx 硬盘分区
  • 原文地址:https://www.cnblogs.com/daishuguang/p/3978409.html
Copyright © 2020-2023  润新知