`
zhouyrt
  • 浏览: 1122671 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

使用隐藏的new来创建对象

阅读更多

JQ中发现的,jQuery.Event类。估计作者是为了减少代码量。定义一个类,但不用new关键字去创建该类对象,而使用方法调用()方式去创建该对象。

 

多数时候我们是这样写类,然后使用new创建对象的。

 

function Person(name,age){
    this.name=name;
    this.age=age;
}
Person.prototype={
    setName : function(n){this.name=n;},
    getName : function(){return this.name;}
}
var p = new Person('jack',25);

 

改成这样的

function Person(name,age){
   //条件改为(this==window)或(this==self)或(this.constructor!=Object)
    if(!this.setName){
       return new Person(name,age);
    }
    this.name=name;
    this.age=age;
}
Person.prototype={
    setName : function(n){this.name=n;},
    getName : function(){return this.name;}
}
var p = Person('jack',25);
 

注意该类较最上面的写类方式中多了以下

 

    if(!this.setName){
       return new Person(name,age);
    }
 

好,创建类的实例(对象)方式也变成了如下:

 

var p = Person('jack',25);

 

这种创建方式(函数调用)较上面的少了“new_”,new和空格,实际上是在类内部new了。而这样方式每次创建对象可以减少4个byte。

 

如果把类内部的if判断条件换成非prototype上的属性,如this.name。程序会提示出错:too much recursion

 

function Person(name,age){
    if(!this.name){
       return new Person(name,age);
    }
    this.name=name;
    this.age=age;
}
Person.prototype={
    setName : function(n){this.name=n;},
    getName : function(){return this.name;}
}
var p = Person('jack',25);
 

 

 

分享到:
评论
15 楼 xing_kenny 2013-01-16  
if(!this.setName){

为什么不直接使用

if( !(this instanceof Person)) ?
14 楼 lgzjw 2010-04-11  
外表看来少了4byte的也就是new 少了,并且window下also不能有if判断的同名对象存在.
13 楼 weiqingfei 2010-04-09  
zhouyrt 写道
weiqingfei 写道
zhouyrt 写道
weiqingfei 写道
直接调用Person方法时,这儿的this指的是window,只有在new Person的时候,this才指的是Person的一个实例,原本这儿就是为了判断是直接调用,还是在new。但是当window里也有这个方法或者属性的时候,就失效了。


说的有道理。
把条件改成以下就可以了,不怕同名的全局函数了。
1,this==window
2,this===window
3,this==self
4,this!=Object


有时候,这个方法的声明,不一定会放在全局(也就是window)上,所以我觉得如果是内部使用的话也就算了,开放给用户用的话不大合适。


诚如jq中jQuery.Event的定义,Event不是全局的而是挂在jQuery上的,这样定义的用!this.preventDefault判断没有问题。或者说即使定义了全局的preventDefault(函数/变量),这个条件也不会失效的。因为jQuery.Event类中的this指向的是jQuery而非window。


因此,这种写法有几个前提。
1,是在定义一个类
2,用new去创建这个类的实例
3,追求极致的精简代码


嗯,其实是一样的,要保证object  jQuery里面没有属性或者方法preventDefault,否则也同样会失效。
但是用户使用jQuery.extend是可以添加这个方法或者属性的。

我没用过jQuery,只是刚开始看它的代码,还不知道jQuery.Event到底怎么用,如果可以开放给用户的话,这个地方就要注意了。
12 楼 蔡华江 2010-04-09  
zhouyrt 写道
蔡华江 写道
还有一个问题就是,这种写法会带来call与apply方法的不正确运行


可以运行,只要正确的传了上下文参数。但这样违背了每次创建对象减少byte的初衷。

以下的p0,p1,p2分别是(),call,apply调用,会发现call,apply创建对象的代码比new还多。

function setName(){};

function Person(name,age){
	if(this==window){//this==self or this.constructor != Object
	   return new Person(name,age);
	}
	this.name=name;
	this.age=age;
}
Person.prototype.setName = function(n){this.name=n;};
Person.prototype.getName = function(){return this.name;}

var p0 = Person('jack',25);
var p1 = Person.call(window,'jack',25);
var p2 = Person.apply(window,['jack',25]);




是不是我要这样认为,你在楼上举的特例是能正常运行的。
可是我调用call与apply时,通常不是放置window作为scope的,如果是那样的话,我直接使用window就行了。
也许我会使用一个Student类来调用,if(this==window)的验证岂不是无效的。
11 楼 zhouyrt 2010-04-09  
蔡华江 写道
还有一个问题就是,这种写法会带来call与apply方法的不正确运行


可以运行,只要正确的传了上下文参数。但这样违背了每次创建对象减少byte的初衷。

以下的p0,p1,p2分别是(),call,apply调用,会发现call,apply创建对象的代码比new还多。

function setName(){};

function Person(name,age){
	if(this==window){//this==self or this.constructor != Object
	   return new Person(name,age);
	}
	this.name=name;
	this.age=age;
}
Person.prototype.setName = function(n){this.name=n;};
Person.prototype.getName = function(){return this.name;}

var p0 = Person('jack',25);
var p1 = Person.call(window,'jack',25);
var p2 = Person.apply(window,['jack',25]);



10 楼 zhouyrt 2010-04-09  
weiqingfei 写道
zhouyrt 写道
weiqingfei 写道
直接调用Person方法时,这儿的this指的是window,只有在new Person的时候,this才指的是Person的一个实例,原本这儿就是为了判断是直接调用,还是在new。但是当window里也有这个方法或者属性的时候,就失效了。


说的有道理。
把条件改成以下就可以了,不怕同名的全局函数了。
1,this==window
2,this===window
3,this==self
4,this!=Object


有时候,这个方法的声明,不一定会放在全局(也就是window)上,所以我觉得如果是内部使用的话也就算了,开放给用户用的话不大合适。


诚如jq中jQuery.Event的定义,Event不是全局的而是挂在jQuery上的,这样定义的用!this.preventDefault判断没有问题。或者说即使定义了全局的preventDefault(函数/变量),这个条件也不会失效的。因为jQuery.Event类中的this指向的是jQuery而非window。


因此,这种写法有几个前提。
1,是在定义一个类
2,用new去创建这个类的实例
3,追求极致的精简代码

9 楼 蔡华江 2010-04-09  
还有一个问题就是,这种写法会带来call与apply方法的不正确运行
8 楼 aninfeel 2010-04-09  
没意义,还会是代码的可读性变差。
7 楼 weiqingfei 2010-04-09  
zhouyrt 写道
weiqingfei 写道
直接调用Person方法时,这儿的this指的是window,只有在new Person的时候,this才指的是Person的一个实例,原本这儿就是为了判断是直接调用,还是在new。但是当window里也有这个方法或者属性的时候,就失效了。


说的有道理。
把条件改成以下就可以了,不怕同名的全局函数了。
1,this==window
2,this===window
3,this==self
4,this!=Object


有时候,这个方法的声明,不一定会放在全局(也就是window)上,所以我觉得如果是内部使用的话也就算了,开放给用户用的话不大合适。
6 楼 蔡华江 2010-04-09  
个人感觉,这个会导致思路上混乱。
5 楼 zhouyrt 2010-04-09  
weiqingfei 写道
直接调用Person方法时,这儿的this指的是window,只有在new Person的时候,this才指的是Person的一个实例,原本这儿就是为了判断是直接调用,还是在new。但是当window里也有这个方法或者属性的时候,就失效了。


说的有道理。
把条件改成以下就可以了,不怕同名的全局函数了。
1,this==window
2,this===window
3,this==self
4,this!=Object
4 楼 weiqingfei 2010-04-08  
直接调用Person方法时,这儿的this指的是window,只有在new Person的时候,this才指的是Person的一个实例,原本这儿就是为了判断是直接调用,还是在new。但是当window里也有这个方法或者属性的时候,就失效了。
3 楼 zhouyrt 2010-04-08  
weiqingfei 写道
这个判断有缺陷
if(!this.setName){  
    return new Person(name,age);  
}  


如果全局有个setName属性或者方法,这个判断就会失效。


感谢提醒,但这是为什么呢?即使加了一次闭包仍然失效。
2 楼 weiqingfei 2010-04-08  
这个判断有缺陷
if(!this.setName){  
    return new Person(name,age);  
}  


如果全局有个setName属性或者方法,这个判断就会失效。
1 楼 lixinlixin2008 2010-04-07  
呵呵,学到了,省的字节虽然少,不过对于追求极致的人来说,还是有用的,对prototype的执行顺序真是理解深刻...

相关推荐

    【05-面向对象(下)】

     –在外部类以外的地方使用非静态内部类创建对象的语法如下:OuterInstance.new InnerConstructor()  –在外部类以外的地方使用静态内部类创建对象的语法如下:new OuterClass.InnerConstructer(); 局部内部类 ...

    java面向对象程序设计.pptx

    下面我们将通过一个具体的实例来理解什么是类,如何定义类、创建对象和使用对象。 时钟类的设计: (1) 数据属性: 时(int hour); 分 (int minute); 秒(int second)。 (2) 行为: 设置时间 setTime() ; 显示...

    C#中new的几种用法详解

    用于创建对象和调用构造函数。 new 修饰符 用于向基类成员隐藏继承成员。 new 约束 用于在泛型声明中约束可能用作类型参数的参数的类型。 new 修饰符(C# 参考) 在用作修饰符时,new 关键字可以显式隐藏从基类...

    原型模式(c++,Qt实现).zip

    用原型实例指定创建对象的种类,并通过拷贝这些原型创建新的对象 从一个对象再创建另外一个可定制的对象,而且不需知道任何创建的细节 克隆的优点 一般在初始信息不发生变化的情况下,克隆是最好的办法,这既...

    C#中,数据集DataSet使用方法大全

    1、创建DataSet对象:DataSet ds = new DataSet("DataSetName"); 2、查看调用SqlDataAdapter.Fill创建的结构 da.Fill(ds,"Orders"); DataTable tbl = ds.Table[0]; foreach(DataColumn col in tbl.Columns) ...

    [java]读书笔记整理:一切都是对象

    随后,释放这些对象的内存空间,以便供其他新的对象使用。也就是说,你根本不必担心内存回收的问题。你只需要创建对象,一旦不再需要,他们就会自行消失。这样做就消除了这类编程问题(即“内存泄漏”),这是由于...

    .net(c#)中的new关键字详细介绍

    1)new 运算符:用于创建对象和调用构造函数。这种大家都比较熟悉,没什么好说的了。2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。3)new 约束:用于在泛型声明中约束可能用作类型参数...

    设计模式经典样例笔记与代码Swift.zip

    这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 [x] 工厂模式 [x] 建造者模式 [x] 原型模式 [x...

    C#基础知识之new关键字介绍

    用于创建对象和调用构造函数。这种大家都比较熟悉,没什么好说的了。 二、修饰符 在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。 无new关键字代码: 有new关键字代码: 结果: 注意: 在子类中用 new...

    C#中new的用法及与override的区别分析

    (1)new是运算符,用于创建对象和调用构造函数。如Class1=new Class1();也可以为值类型调用默认的构造函数如int a=new int();此时a=0. (2)new是修饰符,用于隐藏基类成员的继承成员。override不能隐藏积累成员的继承...

    C#中New关键字的三种用法

     1)new 运算符:用于创建对象和调用构造函数。这种大家都比较熟悉,没什么好说的了。  2)new 修饰符:在用作修饰符时,new 关键字可以显式隐藏从基类继承的成员。  3)new 约束:用于在泛型声明中约束可能...

    【04-面向对象(上)】

    •创建对象的根本途径就是构造器,所以创建对象通过关键字new 加上对应的构造器即可. •如果访问权限允许,类里定义的属性和方法可以通过类或实例来调用, •有static 修饰的访求和属性,既可通过类来调用,也可以通过...

    二十三种设计模式【PDF版】

    用原型实例指定创建对象的种类,并且通过拷贝这些原型创建新的对象。 B. 结构模式 设计模式之 Adapter(适配器) 使用类再生的两个方式:组合(new)和继承(extends),这个已经在 thinking in java中提到过. 设计模式...

    面向对象c#试题参考

    c)在C#中可使用 new 修饰符显式隐藏从基类继承的成员。 d)在C#中要在派生类中重新定义基类的虚函数必须在前面加Override。 5.C#的数据类型有(b) a)值类型和调用类型; b)值类型和引用类型; c)引用类型和关系...

    深入理解C#中new、override、virtual关键字的区别

    在本文中,只具体介绍new作为修饰符的作用,在用作修饰符时,new关键字可以在派生类中隐藏基类的方法,也就说在使用派生类的方法是调用的方法是New关键字新定义出来的方法,而不是基类的方法。在不使用New关键字来

    33种JAVA设计模式DEMO

    这些设计模式提供了一种在创建对象的同时隐藏创建逻辑的方式,而不是使用 new 运算符直接实例化对象。这使得程序在判断针对某个给定实例需要创建哪些对象时更加灵活。 工厂模式(Factory Pattern) 抽象工厂模式...

    《javaScrip开发技术大全》源代码

    • sample06.htm 使用有缺省值的构造函数创建对象 • sample07.htm 使用带方法的构造函数创建对象 • sample08.htm 使用带方法的构造函数创建对象 • sample09.htm 遍历对象属性 •...

    worldwindjava源码-javascript-oop:面向对象编程和面向对象JavaScript

    使用new关键字创建类或原型的实例 定义继承并付诸实践 面向对象编程 面向对象编程 (OOP) 不是一种语言或工具。 OOP 是一种编程风格——我们称之为编程范式。 面向对象编程的四大Struts是: 封装 抽象 遗产 多态性 ...

Global site tag (gtag.js) - Google Analytics