zoukankan      html  css  js  c++  java
  • 关于javascript中的constructor与prototype

    constructor与prototype,先参考这篇文章:constructor与prototype分析

    简单点来说,就是
    1.Function(类)有prototype属性可用,prototype指向一个对象,该对象为所有Function实例共享。
    2.prototype对象有一个constroctor属性,指向Function(类)的构造函数。
    3.所有对象实例都自动拥有prototype对象的所有属性和方法,所以对象实例可直接访问constructor,与Function.prototype.constructor一致。

    下面结合代码来分析分析:

    1.1 声明一个类,类名为F
    function F(name){
    this.name = name;
      console.log("call F()");
    }
    F.name;//function名为F
    F.constructor;//Function(),js默认的constructor,所有function类的constructor属性都一样,直接调用它没有实际意义
    F.prototype;//返回一个对象
    F.prototype.constructor;//F(name),实际的构造器,打印较完整的构造方法签名

    1.2 声明匿名类,类的引用赋给变量FF
    var FF = function(name){
    this.name = name;
    }
    FF.name//function名为空("")
    FF.constructor;//Function(),js默认的constructor,所有function类的constructor属性都一样,直接调用它没有效果!
    [F.constructor===FF.constructor;//true ]
    FF.prototype;//返回一个对象
    FF.prototype.constructor;//function(),只打印粗糙的构造方法签名,因为FF使用了匿名方式声明类


    typeof F;//'function'
    typeof FF;//'function'
    F instanceof Object;//true
    FF instanceof Object;//true

    2.创建对象
    var f = new F("f");//返回对象:Object{name:F}
    f.name;//"f"
    var ff = new FF("ff");
    ff.name;//"ff"

    2.1 直接通用function(类)名的constructor属性,无法创建对象
    var c = new F.constructor();//anonymous(),返回一个匿名函数
    c.name; //anonymous
    从上面分析知道,function名(类名).constructor返回的都是内容为"Function()"的函数,new F.constructor()相当于 new Function(),得到的将是
    空函数实现,类似java中的空类,什么也不做。所以用"function名.constructor"做的操作是没有意义的,除非给它重新赋值。
    以下无意义:
    F.constructor.call(...);//返回anonymous()
    new F.prototype.constructor(...)

    2.2 通过prototype访问constructor,创建新的对象实例
    F.prototype;//Object{constructor:function{}} prototype对象
    默认的prototype有一个constructor指针指向function类的构造方法本身:
    var obj = new F.prototype.constructor("obj");//F{name='obj'} 与new F("obj")效果一样
    注意:只有function才有prototype属性,其它类型的对象没有prototype属性
    至于说对象含有constructor,其实该constructor属性,是其类的prototype拥有的,被对象共享了而已

    2.3 通过对象实例访问constructor,创建新的对象实例
    我们知道,所有对象实例都共享类的prototype,那么prototype中的constructor也可以被所有对象实例调用。
    f.constructor === F.prototype.constructor //true 此为证据

    var c = new f.constructor("c");//Object{name:c} 与new F("c")效果一样
    c.name;//'c'

    适用场合:知道一个对象,想创建这个对象所属类的新实例,不必知道该对象所属的类是什么。
    前提:必须知道constructor的构造参数
    extjs3.x的Record.copy()中即用了该方法:
    copy : function(newId) {
      return new this.constructor(Ext.apply({}, this.data), newId || this.id);
    },

    3.调用构造函数(construtor)
    找到了构造函数,可以调用它,也可以new它,上面的讨论是new constructor(),效果和new Function()是一样的。
    而调用是指constructor.call(...),call()一般是用于覆盖或继承,如:
    var myObj = {};
    F.prototype.constructor.call(myObj,"myName");
    运行后,myObj就拥有了F的属性和方法:Object{name="myName"},如果myObj中有相同的属性则会被覆盖。

    4.关于调用与new
    调用返回值与function的返回值有关,返回什么就是什么,
    而new不一样,new返回的是新生成的对象,与function内是否有返回值无关,即使定义了返回值也无效。
    调用constructor是为了将它内部的代码逻辑附加到我们指定的对象上,而不是为了生成新对象。
    var F = function(id,name){
      this.id = id;
      this.name = name;
      return id + ':'+ name;
    }
    比较 F('1','qin')与new F('1','qin');

    5.关于Function与function
    我想可以这么理解,Function与function的关系就像Object与{},
    String  --""
    Array  ---[]
    Object  --{}
    Function --function(){....}
    new Function():new出来的是一个function,就像new Object()出来的是一个对象一样。
    使用方式:
    var F = new Function('id','name',"this.id=id;this.name=name;return id +':'+ name");//参数分开写
    或 F = new Function('id,name',"this.id=id;this.name=name;return id +':'+ name");//参数合起来写
    前面的参数做为参数,最后一个参数是方法体。
    与下面的定义等效:
    var F = function(id,name){
      this.id = id;
      this.name = name;
      return id + ':'+ name;
    }
    1.调用function
    F('2','qin');//输出"2:qin"
    2.用function创建对象
    new F('1','myName');//返回生成的对象. anonymous{ id="1", name="myName"}
    Extjs3源码中JsonReader.createAccessor()使用new Function(...)对复杂json对象的属性访问进行处理:
    createAccessor : function(){
            var re = /[\[\.]/;
            return function(expr) {
                if(Ext.isEmpty(expr)){
                    return Ext.emptyFn;
                }
                if(Ext.isFunction(expr)){
                    return expr;
                }
                var i = String(expr).search(re);
                if(i >= 0){
                    return new Function('obj', 'return obj' + (i > 0 ? '.' : '') + expr);
                }
                return function(obj){
                    return obj[expr];
                };
            };
        }()

  • 相关阅读:
    15 个 Android 通用流行框架大全
    android将drawable下的图片转换成bitmap
    android横屏布局文件设置
    高级运维(五):构建memcached服务、LNMP+memcached、使用Tomcat设置Session、Tomcat实现session共享
    高级运维(四):Nginx常见问题处理、安装部署Tomcat服务器、使用Tomcat部署虚拟主机
    高级运维(三):部署Lnmp环境、构建Lnmp平台、地址重写
    高级运维(二):搭建Nginx服务器、用户认证、基于域名的虚拟主机、SSL虚拟主机、Nginx反向代理
    高级运维(一):反向代理&使用Varnish加速Web
    Linux 软硬链接区别
    Linux 常用的一些操作
  • 原文地址:https://www.cnblogs.com/qinxike/p/3045466.html
Copyright © 2011-2022 走看看