`
simohayha
  • 浏览: 1400091 次
  • 性别: Icon_minigender_1
  • 来自: 火星
社区版块
存档分类
最新评论

在javascript中如何判断一个方法是new调用还是一般调用

阅读更多
在看The.Art.and.Science.of.JavaScript 的时候,看到了这个问题,就是在javascript中如何判断一个方法是new调用还是一般调用,在书中给出的代码是

function Element(){
   if(this==window || 'Element' in this){
      console.log("normal");
}else{
     console.log("new");
}

}


可是这个代码不能解决两个问题:

1比如加上下面的代码:

 Element.prototype.Element=1; 


这时如果调用new Element()时,由于Element 已经存在于this里面,因此会打印出normal;

这个很好解决。我是这样写的:

function Element(){
if(this.__proto__==Element.prototype)
{console.log("new");}else{console.log("normal");}}


可是这时又有了第二个问题。

比如下面的代码:

var test= new Element();

test.temp=Element;

test.temp();


这时的调用,也应该是normal的调用,可是依然打印出new.

实在想不出来怎么解决第二种情况,因此发出来看那位能够解决这个问题.

分享到:
评论
12 楼 achun 2008-05-04  
笨笨狗 写道
achun 写道
LS最后写的这个,感觉比我写的那个有水准.
this.name VS arguments.callee
呵呵,当然是arguments.callee看上去更美丽了.


不止是看上去更美丽,先来看你的代码:


function Element(){    
   if(this.name==undefined){    
       console.log("new");    
   }else{    
      console.log("normal");    
   }  
}  
 


试试在调用这段代码之前干这事:


var name;
Element(); //出现意外了吧,呵呵



确实,偶这个是错误的.理论上就有问题.
IE不过,FF过了,是FF的BUG?
11 楼 yyliuliang 2008-05-04  
this.toString().match(/( \w+)/)[0]
10 楼 笨笨狗 2008-05-04  
achun 写道
LS最后写的这个,感觉比我写的那个有水准.
this.name VS arguments.callee
呵呵,当然是arguments.callee看上去更美丽了.


不止是看上去更美丽,先来看你的代码:


function Element(){    
   if(this.name==undefined){    
       console.log("new");    
   }else{    
      console.log("normal");    
   }  
}  
 


试试在调用这段代码之前干这事:


var name;
Element(); //出现意外了吧,呵呵


9 楼 笨笨狗 2008-05-04  
笨笨狗 写道



var t = new Test();
t.Test = Test;
t.Test();





而且,就算不阻止构造函数实例化对象,换个角度来看,这段代码也没超出我们的预期,因为把Test赋值给一个对象作为其属性然后调用,实际上已经不再算是原始的构造函数了吧,虽然也是引用……
8 楼 achun 2008-05-04  
LS最后写的这个,感觉比我写的那个有水准.
this.name VS arguments.callee
呵呵,当然是arguments.callee看上去更美丽了.
7 楼 笨笨狗 2008-05-04  
对于我的需求,也就是“当函数被用作new的时候,抛出异常”来说,我上面的解决办法就已经很完美了,因为都不存在之前被new出来的实例对象,那么后面那个故意让其失效的方法就不能运作了,所以这样就够了:

function Test(){
    if(this instanceof arguments.callee){
        throw new Error("不能做实例化操作!");
    }
    console.log("普通调用");
}


因为此时已经不可能有一个Test的实例对象来调用本身了,也就是说下面这段代码被避免了:


var t = new Test();
t.Test = Test;
t.Test();



如果不阻止构造函数实例化对象,那么上面的代码是可以运行的,但是现在没有意外了:)
6 楼 s79 2008-05-04  
自造构造函数不使用new,直接return新建对象,这样new不new是一样的,就省的费劲判断了。o(∩_∩)o...
5 楼 csf178 2008-05-03  
再怎么写也只能找到更多的必要条件 没有充分条件

至于这个 this.testTimeStamp=new Date().getTime(); 纯粹是自找麻烦
想要伪造很容易 delete了testTimeStamp怎么办?
4 楼 afcn0 2008-05-03  
讨论下这个问题,new之前创建了一个空对象,并且隐藏继承了构造函数的原形,然后以这个空对象为this执行构造函数,如果构造函数当中没有return object,那就是返回this对象,所以其实就是普通的运行构造函数,想要区分,比较好的就是

function test(){
if (this instanceof arguments.callee && (!this.testTimeStamp || this.testTimeStamp<new Date().getTime())) 
{
this.testTimeStamp=new Date().getTime();
..........
}
else
{
一般.......
}
}

3 楼 achun 2008-05-03  
我这样写:
function Element(){  
  if(this.name==undefined){  
      console.log("new");  
}else{  
     console.log("normal");  
}
}
2 楼 hax 2008-02-27  
我个人一直是这么写的:

function ClassA() {
  assert (this instanceof ClassA);
  // constructing our instance
}

有时候也会这样:

function CustomError(msg) {
  if (this instanceof CustomError) {
    // constructiing...
  } else {
    return new CustomError(msg);
  }
}
1 楼 笨笨狗 2008-02-27  
楼主第二个方法,那个__proto__属性只有ff支持,所以也不完美。
一开始我这么写
function Element(){  
    if(this.constructor===arguments.callee){ // this instanceof arguments.callee 也是一样的效果
        console.log("new");
    }else{
        console.log("normal");
    }
} 

看起来还不错,但是:
a = new Element;
a.Element = Element;
a.Element() //完蛋,告诉我是new

然后,又想,既然new的话,this肯定是个新对象,这个对象不会是window,也不会是window的属性,那好,这样
function Element(){ 
    var flag = "new"
    if(this===window){
       flag = "normal";
    }else{
        for(var i in window){
            if(this===window[i]){
                flag = "normal";
            }
        }
    }
    console.log(flag)
} 

貌似不错,但是,但是:
a = {b:{Element:Element}}
a.b.Element() //依然是new!现在this是b,当然不在window下,new的this肯定不在window下,但是反过来说不一定,晕倒



由于js中的函数是游离的,this可以动态改变,所以要真正解决这个问题应该很困难,但是如果限定在一定的范围内,比如说,不在对象引用构造函数本身,那this instanceof arguments.callee这样的判断就足够了。之所以探讨这个问题,是因为看了Pro javascript design paterns,里面有实现Interface,但是我觉得他那个检测太弱了,准备自己实现一个更严格的Interface,用来限定某个对象的属性类型、方法参数个数以及返回值。这样又引出一个问题,我们知道java里面的Interface是不可以实例化的,所以js实现的话需要判断一下Interface这个函数是不是被new了,如果是,就抛异常……

相关推荐

    javascript调用delphi中的函数

    3. **JavaScript调用COM组件**:在JavaScript中,可以通过`new ActiveXObject(Progid)`来实例化一个Delphi编写的COM组件,其中`Progid`是组件的程序标识符。然后,可以调用该对象的公开方法和属性。 4. **Delphi...

    vbscript和javascript互相调用方法

    例如,如果你想从VBScript调用一个名为`myFunc`的JavaScript函数,你可以这样做: ```vbscript Dim myObj Set myObj = Server.CreateObject("Scripting.Dictionary") myObj.Language = "JScript" myObj.Add "myFunc...

    JavaScript中判断函数是new还是()调用的区别说明

    在JavaScript中,判断函数是通过new运算符创建实例的方式调用,还是通过普通函数调用,通常涉及到几种不同的方法和它们的局限性。下面将详细介绍每种判断方式及其适用场景和潜在问题。 首先,为了区分new调用和普通...

    在javascript函数中调用com组件的属性和方法

    在JavaScript函数中调用COM组件的属性和方法是指在JavaScript代码中使用COM组件提供的属性和方法来实现各种功能。本文将介绍如何在JavaScript函数中调用COM组件的属性和方法,并提供一个实例演示如何使用COM组件来...

    c# winform 中怎样来调用B/S中的JavaScript的方法

    在C# WinForm应用中调用B/S架构中的JavaScript方法主要涉及到的是客户端与服务器端的交互问题。在传统的Web开发中,B/S架构通常由浏览器(客户端)与服务器(后端)组成,而C# WinForm是桌面应用程序,它们之间进行...

    ActionScript与JavaScript相互调用

    具体做法是在Flash中编写一个函数,该函数作为参数传递给`getURL()`,并指向一个包含JavaScript函数的URL。 - **在JavaScript中调用Flash**:使用HTML文档对象模型(DOM)中的特定语法。对于Internet Explorer浏览器...

    Android调用JavaScript.zip

    "Android调用JavaScript.zip"这个压缩包可能包含了关于如何在Android中调用JavaScript代码的相关示例和资源。下面我们将深入探讨这一主题。 1. **WebView组件** Android中的WebView是一个可以加载和显示网页的控件...

    Android中调用js方法及js中调用本地方法

    首先,创建一个Java类,并标记其方法为`@JavascriptInterface`,这样它们就可以在JavaScript中被调用: ```java public class MyJavaScriptInterface { @JavascriptInterface public void callFromJs(String ...

    java javascript 调用命令行 cmd

    在IT领域,有时候我们需要在Java或JavaScript代码中执行操作系统级别的命令,例如运行系统脚本、管理文件、控制进程等。这种需求通常通过调用命令行(CMD)来实现。本文将详细探讨如何在Java和JavaScript中调用...

    在c++中调用Javascript(MFC源码)

    在C++中调用JavaScript是一项复杂但非常有用的技术,特别是在开发跨平台应用程序或者需要与Web交互的桌面应用时。MFC(Microsoft Foundation Classes)是微软提供的一个C++库,用于构建Windows应用程序。在这个场景...

    Java调用javaScript代码

    本文将深入探讨“Java调用JavaScript代码”的技术实现,以及它在实际项目中的应用场景。 Java和JavaScript虽然名字相似,但它们是两种完全不同的编程语言,各自有其特定的用途。Java是一种静态类型的、面向对象的...

    JavaScript与安卓交互之JS调用安卓方法

    在现代的移动应用开发中,JavaScript与Android的交互是一个常见的需求,特别是在混合应用开发中,如使用Apache Cordova、React Native或Ionic等框架。本文将深入探讨如何通过JavaScript调用Android原生方法,以实现...

    QT和网页中的JavaScript函数进行相互调用的实现

    - 在QT中定义一个槽函数,例如`handleJsCall`,然后使用`QWebChannel`来创建一个通信通道,让JavaScript可以调用这个槽函数。 - 首先,创建一个继承自`QObject`的C++类,暴露槽函数给JavaScript。比如,创建一个`...

    函数之间调用同一个对象方法

    在给定的例子中,“函数之间调用同一个对象方法”指的是在一个函数内部创建对象并调用其方法,然后在另一个函数中再次调用同一对象的相同或不同方法。这种模式常见于事件驱动的编程环境,例如游戏开发或GUI应用程序...

    Javascript中调用C++函数

    这个中间层通常是一个库或插件,它在JavaScript环境中暴露C++函数,使得JavaScript能够调用它们。 在MFC框架下,我们可以使用ActiveX控件或NPAPI(Netscape Plugin API)插件来创建这个中间层。ActiveX是微软开发的...

    aspnet用javascript或者是HTML调用CS文件中的方法

    创建一个Web服务(ASMX)可以让JavaScript直接调用CS文件中的方法。首先,创建一个ASMX文件,并定义一个Web方法: ```csharp [WebService(Namespace = "http://tempuri.org/")] [WebServiceBinding(ConformsTo = ...

    JavaScript中函数对象调用模式总结

    JavaScript中的函数对象调用模式是编程中至关重要的概念,它涉及到函数作为一等公民、作用域、闭包、原型链等多个核心知识点。这篇博客通过深入分析JavaScript中的函数调用模式,帮助开发者更好地理解和掌握这些概念...

    几种在网页中调用其它页面的方法

    这种方法可以在当前页面中加载其它页面的内容,但是需要注意的是,这种方法只能在同一个域名下使用。 方法二:使用Server Side Include(SSI) 使用SSI可以在服务器端包含其它页面的内容。例如: ``` &lt;!--#include...

    c# winform webbrowser页面中js调用winform类方法

    现在,你可以在网页的JavaScript代码中调用这个暴露的方法了。假设网页的HTML代码如下: ```html ()"&gt;调用C#方法 function callCSharpMethod() { var csharpObj = window.external; if (csharpObj && ...

    xe7android手机调用javascript

    本文将详细讲解如何在Android设备上实现Java代码调用JavaScript,以及JavaScript反过来调用Android Java代码的方法。 一、Android调用JavaScript 1. 使用`WebView`:Android中的`WebView`组件用于加载和显示网页...

Global site tag (gtag.js) - Google Analytics