关于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];
            };
        };
    }()

posted on 2013-04-26 18:35  qinxike  阅读(364)  评论(0编辑  收藏  举报

导航