จะตรวจสอบได้อย่างไรว่าฟังก์ชั่นมีอยู่ในจาวาสคริปต์?


533

รหัสของฉันคือ

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

อย่างไรก็ตามบางครั้งฉันonChangeไม่โหลด ข้อผิดพลาด Firebug ด้วย

me.onChange ไม่ใช่ฟังก์ชั่น

ฉันต้องการที่จะลดระดับลงอย่างงดงามเพราะนี่ไม่ใช่คุณสมบัติที่สำคัญที่สุดในโปรแกรมของฉัน typeofให้ข้อผิดพลาดเดียวกัน

ข้อเสนอแนะใด ๆ เกี่ยวกับวิธีการตรวจสอบให้แน่ใจว่ามันมีอยู่แล้วเท่านั้นดำเนินการonChange?

(ไม่มีวิธีใดด้านล่างยกเว้นลองใช้งานเดียว)


1
@ SteveChambers ฉันได้ทำสิ่งนั้นแล้ว ขอบคุณที่เตือนฉัน
Alec Smart


จับข้อยกเว้น ตรวจสอบคำตอบของฉัน
Matteus Barbosa

คำตอบ:


1225

ลองสิ่งนี้:

if (typeof me.onChange !== "undefined") { 
    // safe to use the function
}

หรือดีกว่ายัง (ตามความคิดเห็น UpTheCreek upvoted)

if (typeof me.onChange === "function") { 
    // safe to use the function
}

249
=== 'ฟังก์ชั่น' จะดีกว่า! = 'ไม่ได้กำหนด'
UpTheCreek

3
@James เนื่องจากคำสั่งนั้นมีundefinedข้อผิดพลาดเกิดขึ้นจริงใน JavaScript ฉันลองแล้ว
Mike Perrenoud

8
@UpTheCreek มันจะเป็นบิตอันตรายตามแก้ปัญหาทั่วไปตั้งแต่รุ่นเก่าของ IE typeof window.alert === 'object'รักษาฟังก์ชั่นบางอย่างที่เป็นวัตถุเช่น
Noyo

1
ทำไมไม่ใช้เพียงif (me.onChange) { // do something }?
BornToCode

3
@BornToCode เพราะme.onChangeอาจเป็นสิ่งที่ประเมินtrueได้ไม่จำเป็นต้องมีฟังก์ชั่น (เช่นมันอาจจะเป็นบูลีนสตริง ฯลฯ ) ตัวอย่างเช่นดูjsfiddle.net/j5KAF/1
Ohad Schneider

108

ฉันมีปัญหานี้

if (obj && typeof obj === 'function') { ... }

ยังคงโยนข้อผิดพลาดอ้างอิงถ้า obj เกิดขึ้นที่จะไม่ได้กำหนด

ในที่สุดฉันก็ทำสิ่งต่อไปนี้:

if (typeof obj !== 'undefined' && typeof obj === 'function') { ... }

เพื่อนร่วมงานคนหนึ่งชี้ให้ฉันเห็นว่าการตรวจสอบถ้าเป็น!== 'undefined'แล้ว=== 'function'จะซ้ำซ้อนของหลักสูตร

เรียบง่าย:

if (typeof obj === 'function') { ... }

ทำความสะอาดและใช้งานได้ดีมาก


1
ใครมีความคิดว่าทำไมข้อมูลโค้ดแรกพ่นReferenceError? นั่นดูไร้เหตุผลสำหรับฉัน
saidfagan

@saidfagan ดูคำจำกัดความของReferenceError developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Misha Nasledov

สิ่งนี้ใช้ได้กับฉัน
NewBie1234

1
อะไรคือสาเหตุที่ทำให้ typeof obj == 'function' ไม่เพียงพอ? ;-) คำเตือน: ผู้ดำเนินการทดสอบความเท่าเทียมอย่างเข้มงวดจะใช้งานได้ก็ต่อเมื่อตัวถูกดำเนินการคงที่ว่างเปล่าหรือเป็นโมฆะหรือ 0 หรืออาจมีการรวมกันของนักแสดงเช่นนี้
Fabien Haddadi

16

หากคุณใช้ eval ในการแปลงสตริงเป็นฟังก์ชั่นและคุณต้องการตรวจสอบว่ามีวิธีการ eval'd อยู่หรือไม่คุณจะต้องใช้typeofและสตริงฟังก์ชันของคุณภายในeval :

var functionString = "nonexsitantFunction"
eval("typeof " + functionString) // returns "undefined" or "function"

อย่าย้อนกลับนี้และลองtypeofบนEVAL หากคุณทำ ReferenceError จะถูกโยน:

var functionString = "nonexsitantFunction"
typeof(eval(functionString)) // returns ReferenceError: [function] is not defined

21
eval == evil;)
Yeti

1
มันอาจเป็นความชั่วร้าย แต่สิ่งนี้มีประโยชน์มากเมื่อชื่อฟังก์ชันอยู่ในตัวแปร
ลุคลูกพี่ลูกน้อง

8
คุณสามารถทำสิ่งนี้ได้โดยไม่ต้องทำ Eval ตัวอย่าง:var a = 'alert'; window[a]('it works');
zennin

15

เกี่ยวกับ:

if('functionName' in Obj){
    //code
}

เช่น

var color1 = new String("green");
"length" in color1 // returns true
"indexOf" in color1 // returns true
"blablabla" in color1 // returns false

หรือสำหรับกรณีของคุณ:

if('onChange' in me){
    //code
}

ดูเอกสาร MDN


แต่วิธีนี้ไม่ทำงานทุกครั้ง :( เช่นถ้าฉันต้องการทราบว่ามีlastIndexOf()ในสตริง (เรารู้ว่าเป็น แต่ในทางทฤษฎี) typeof String().lastIndexOf === "function"มันเป็นความจริง แต่'lastIndexOf' in Stringเป็นเท็จ #
5252

10

ลองtypeof- มองหา'undefined'เพื่อบอกว่ามันไม่มีอยู่จริง'function'สำหรับฟังก์ชั่น JSFiddle สำหรับรหัสนี้

function thisishere() {
    return false;
}
alert("thisishere() is a " + typeof thisishere);
alert("thisisnthere() is " + typeof thisisnthere);

หรือเป็นถ้า:

if (typeof thisishere === 'function') {
    // function exists
}

หรือด้วยค่าส่งคืนในบรรทัดเดียว:

var exists = (typeof thisishere === 'function') ? "Value if true" : "Value if false";
var exists = (typeof thisishere === 'function') // Returns true or false

9

ไม่เห็นสิ่งนี้แนะนำ: me.onChange && me.onChange (str);

โดยทั่วไปถ้า me.onChange ไม่ได้ถูกกำหนด (ซึ่งจะเป็นถ้ายังไม่ได้เริ่ม) แล้วมันจะไม่ดำเนินการส่วนหลัง ถ้า me.onChange เป็นฟังก์ชั่นมันจะดำเนินการ me.onChange (str)

คุณสามารถไปต่อและทำ:

me && me.onChange && me.onChange(str);

ในกรณีที่ฉันเป็น async เช่นกัน


5
//Simple function that will tell if the function is defined or not
function is_function(func) {
    return typeof window[func] !== 'undefined' && $.isFunction(window[func]);
}

//usage

if (is_function("myFunction") {
        alert("myFunction defined");
    } else {
        alert("myFunction not defined");
    }

วิธีการแก้ปัญหาของคุณไม่ชัดเจนเพราะมันขัดแย้งกับ jQuery ซึ่งเป็นเรื่องแปลกในขณะนี้ฉันคิดว่าดังนั้นมันจะพ่นข้อผิดพลาดเมื่อทำการทดสอบอย่างง่าย
T.Todua

@tazotodua มันเป็นฟังก์ชั่นอธิบายตนเอง ถ้าคุณต้องการใช้โดยไม่มี jquery เพียงลบส่วน && นั่นเป็นเงื่อนไขพิเศษในการตรวจสอบและหลีกเลี่ยงข้อผิดพลาด
มูฮัมหมัด Tahir

เงื่อนไขทางด้านซ้าย&&ของสิ่งที่ดูแล jQuery isFunctionทางด้านขวาของสิ่ง&&นั้นหรือไม่?
SantiBailors

5

สำหรับฉันวิธีที่ง่ายที่สุด:

function func_exists(fname)
{
  return (typeof window[fname] === 'function');
}

นี่คือคำตอบที่ถูกต้องเพราะมันเป็นครอกสตริง .. ฉันจะบอกว่าดีกว่าเช่นนี้if ((typeof window["function_name"] !== 'undefined') && ((typeof window["function_name"] === 'function'))) { return true; } else { return false; }แต่มันเป็นการปรับตัวเล็กน้อย
Mr Heelis

4

ฉันจะไปอีก 1 ขั้นเพื่อให้แน่ใจว่าคุณสมบัตินั้นเป็นฟังก์ชั่น

function js_to_as( str ){
     if (me && me.onChange && typeof me.onChange === 'function') {
         me.onChange(str);
     }
}


3

ฉันชอบใช้วิธีนี้:

function isFunction(functionToCheck) {
  var getType = {};
  return functionToCheck && getType.toString.call(functionToCheck) === '[object Function]';
}

การใช้งาน:

if ( isFunction(me.onChange) ) {
    me.onChange(str); // call the function with params
}


3
function function_exists(function_name)
{
    return eval('typeof ' + function_name) === 'function';
}
alert(function_exists('test'));
alert(function_exists('function_exists'));

หรือ

function function_exists(func_name) {
  //  discuss at: http://phpjs.org/functions/function_exists/
  // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
  // improved by: Steve Clay
  // improved by: Legaev Andrey
  // improved by: Brett Zamir (http://brett-zamir.me)
  //   example 1: function_exists('isFinite');
  //   returns 1: true

  if (typeof func_name === 'string') {
    func_name = this.window[func_name];
  }
  return typeof func_name === 'function';
}

1
กรุณาอธิบายบางอย่าง
Gufran Hasan

ในสองกรณีเพียงเรียกfunction_existsพร้อมชื่อพารามิเตอร์ฟังก์ชั่นเพื่อตรวจสอบการมีอยู่ส่งคืนบูล
โมฮัมหมัด Lotfi

3

ใส่เครื่องหมายอัศเจรีย์คู่เช่น !! หน้าชื่อฟังก์ชันที่คุณต้องการตรวจสอบ ถ้ามีอยู่มันจะกลับมาจริง

function abc(){
}
!!window.abc; // return true
!!window.abcd; // return false

3

ในคำไม่กี่คำ: จับข้อยกเว้น

ฉันแปลกใจจริงๆที่ไม่มีใครตอบหรือแสดงความคิดเห็นเกี่ยวกับข้อยกเว้นในโพสต์นี้

รายละเอียด: ต่อไปนี้เป็นตัวอย่างที่ฉันพยายามจับคู่ฟังก์ชั่นซึ่งนำหน้าด้วย mask_ และต่อท้ายด้วยฟิลด์ชื่อ "ชื่อ" เมื่อจาวาสคริปต์ไม่พบฟังก์ชั่นก็ควรโยนReferenceErrorซึ่งคุณสามารถจัดการตามที่คุณต้องการในส่วนที่จับ

function inputMask(input) {
  try {
    let maskedInput = eval("mask_"+input.name);

    if(typeof maskedInput === "undefined")
        return input.value;
    else
        return eval("mask_"+input.name)(input);

  } catch(e) {
    if (e instanceof ReferenceError) {
      return input.value;
    }
  }
}


2

โดยไม่มีเงื่อนไข

me.onChange=function(){};

function getID( swfID ){
     if(navigator.appName.indexOf("Microsoft") != -1){
          me = window[swfID];
     }else{
          me = document[swfID];
     }
}

function js_to_as( str ){
     me.onChange(str);
}

2

ฉันสงสัยmeว่าไม่ได้รับการกำหนด onload อย่างถูกต้อง

การย้ายการเรียก get_ID ไปยังเหตุการณ์ onclick ควรดูแล

เห็นได้ชัดว่าคุณสามารถต่อกับดักเป็นที่กล่าวถึงก่อนหน้านี้:

function js_to_as( str) {
  var me = get_ID('jsExample');
  if (me && me.onChange) {
    me.onChange(str);
  }
}

2

ฉันมักจะตรวจสอบดังนี้:

if(!myFunction){return false;}

เพียงวางไว้ข้างหน้ารหัสใด ๆ ที่ใช้ฟังก์ชันนี้


2

ฉันมีกรณีที่ชื่อของฟังก์ชั่นที่แตกต่างกันตามตัวแปร (var 'x' ในกรณีนี้) เพิ่มชื่อฟังก์ชั่น งานนี้:

if ( typeof window['afunction_'+x] === 'function' ) { window['afunction_'+x](); } 


2

ฉันได้ลองคำตอบที่ยอมรับแล้ว แต่:

console.log(typeof me.onChange);

ส่งคืน 'undefined' ฉันสังเกตเห็นว่าข้อกำหนดระบุเหตุการณ์ที่เรียกว่า 'onchange' แทนที่จะเป็น 'onChange' (สังเกต camelCase)

การเปลี่ยนคำตอบที่ยอมรับดั้งเดิมเป็นสิ่งต่อไปนี้ใช้ได้สำหรับฉัน:

if (typeof me.onchange === "function") { 
  // safe to use the function
}

2

หากคุณกำลังตรวจสอบฟังก์ชันที่เป็นปลั๊กอิน jQuery คุณต้องใช้ $ .fn.myfunction

if (typeof $.fn.mask === 'function') {
    $('.zip').mask('00000');
}

2

ฉันยังคงมองหาวิธีการแก้ปัญหาที่สง่างามสำหรับปัญหานี้ หลังจากไตร่ตรองมากฉันพบว่าวิธีนี้ดีที่สุด

const func = me.onChange || (str => {}); func(str);


หากคุณต้องการความเรียบง่ายคุณสามารถทำสิ่งนี้ได้: (me.onChange||(_=>_))()จะเรียกใช้ฟังก์ชันถ้ามีอยู่มิฉะนั้นจะไม่ทำอะไรเลย
JSideris

มันจะดีกว่าme.onChange && me.onChange()เพื่อป้องกันการกำหนดฟังก์ชั่นโมฆะ
necrifede

2

Javascript สมัยใหม่เพื่อช่วยเหลือ!

สิ่งนี้อาจไม่มีโอกาสที่ดีที่จะได้เห็นรายการคำตอบที่ยาว แต่ตอนนี้ได้รับการแก้ไข * ในระดับภาษาด้วยไวยากรณ์ตัวเลือกการเชื่อมโยงใหม่

me.onChange?.(str)

มันเป็นเรื่องง่ายเหมือนที่ -onChangeเพียงได้รับเรียกว่าถ้ามันมีอยู่

หากonChangeไม่มีอยู่ไม่มีอะไรเกิดขึ้นและนิพจน์คืนค่าundefined- ดังนั้นหากมีค่าส่งคืนที่คุณใช้เป็นอย่างอื่นคุณสามารถตรวจสอบค่านี้ได้!== undefinedก่อนดำเนินการต่อ

ขอบกรณีข้อแม้ - ถ้าonChange ไม่อยู่ แต่เป็นไม่ได้ฟังก์ชั่นที่คุณจะได้รับTypeErrorฟังก์ชั่นที่คุณจะได้รับนี่คือสิ่งที่คุณคาดหวังมันเหมือนกับการพยายามเรียกฟังก์ชั่นที่ไม่ใช่ฟังก์ชั่นใด ๆ แต่ก็คุ้มค่าที่จะชี้ให้เห็นอย่างชัดเจนว่าการผูกมัดทางเลือกไม่ได้ใช้เวทมนตร์เพื่อทำให้สิ่งนี้หายไป

* การพูดทางเทคนิคที่เป็นตัวเลือก Chaining ยังคงเป็นข้อเสนอ TC39 ขั้นที่ 4ดังนั้นจึงยังไม่อยู่ในข้อมูลจำเพาะของ ECMAScript แต่ขั้นตอนที่ 4 หมายถึงการสรุปและการรับประกันนั้นรวมอยู่แล้วก็รอรุ่นใหม่ที่จะส่ง คุณสามารถใช้ไวยากรณ์ในเวอร์ชันสุดท้ายวันนี้ผ่าน Babel ด้วยความมั่นใจว่าจะไม่เปลี่ยนแปลง มันยังอยู่ใน typescript!


1

นี่คือวิธีแก้ปัญหาที่ใช้งานง่ายสำหรับตรวจสอบการมีอยู่ของฟังก์ชันและเรียกใช้ฟังก์ชันนั้นแบบไดนามิกโดยฟังก์ชันอื่น

ฟังก์ชันทริกเกอร์

function runDynamicFunction(functionname){ 

    if (typeof window[functionname] == "function") { //check availability

        window[functionname]("this is from the function it"); // run function and pass a parameter to it
    }
}

และตอนนี้คุณสามารถสร้างฟังก์ชั่นแบบไดนามิกอาจจะใช้ php เช่นนี้

function runThis_func(my_Parameter){

    alert(my_Parameter +" triggerd");
}

ตอนนี้คุณสามารถเรียกใช้ฟังก์ชันโดยใช้เหตุการณ์ที่สร้างขึ้นแบบไดนามิก

<?php

$name_frm_somware ="runThis_func";

echo "<input type='button' value='Button' onclick='runDynamicFunction(\"".$name_frm_somware."\");'>";

?>

รหัส HTML ที่แน่นอนที่คุณต้องการคือ

<input type="button" value="Button" onclick="runDynamicFunction('runThis_func');">

0
    function sum(nb1,nb2){

       return nb1+nb2;
    }

    try{

      if(sum() != undefined){/*test if the function is defined before call it*/

        sum(3,5);               /*once the function is exist you can call it */

      }

    }catch(e){

      console.log("function not defined");/*the function is not defined or does not exists*/
    }

0

แล้วมีสิ่งนี้ ...

( document.exitPointerLock || Function )();

สวัสดีท่านอาจารย์เก่ง แต่ท่านคิดอย่างไรเกี่ยวกับการยกเว้น ตรวจสอบคำตอบของฉัน
Matteus Barbosa

สวัสดีขอบคุณสำหรับบันทึก โซลูชันของคุณน่าชื่นชม ฉันพยายามหลีกเลี่ยงกระบวนทัศน์ 'ลองจับ' ทุกครั้งที่ทำได้หรือง่ายกว่าหรืออาจเป็นเพราะความช่วยเหลือจากบุคคลที่สาม 'Eval' ยังขมวดคิ้วด้วยเหตุผลหลายประการเช่นการลองจับเสื้อคลุมตัวอื่นเพื่อให้เวลาล่าช้า มีทางเลือกอื่น ๆ ในการปรับเปลี่ยนที่อาจ 'โยน' ได้เช่นกัน ฉันคิดว่า 'ฟังก์ชั่นใหม่ (parms, body)' อาจจะทำให้คุณเกิดข้อผิดพลาด แต่ฉันเดาว่าคำถามต่อไปสำหรับฉันคือการเปรียบเทียบความเร็วอื่น ๆ แล้วลดขนาดรหัสที่ดีที่สุด (หมายถึงฉันเร็วกว่า) [อืมมันดูใหม่ ฉันไม่ได้ลองเลย jsben.ch]
อาจารย์เจมส์

mmm rly จุดที่น่าสนใจเกี่ยวกับการเรียกใช้ฟังก์ชั่นใหม่แทน อย่าลังเลที่จะส่งคำแนะนำการเปลี่ยนแปลงของคุณไปยังคำตอบของฉัน ขอบคุณมาก
Matteus Barbosa

ใช่ฉันหมายถึงแม้ในการทุบตีโดยใช้ 'source myScript.sh' จะช่วยให้คุณสามารถ 'ส่งออก' ผ่านนามแฝงและอื่น ๆ มันก็เหมือนคลาสและห้องสมุดมักจะเป็นคุณสมบัติโดยธรรมชาติของรหัสใด ๆ และทุกรหัส คุณควรมีรหัสตรวจสอบล่าม js หากยังไม่ได้รับการอนุมัติอย่างแน่นอน ฉันสร้างฟังก์ชั่นเดียวในฟังก์ชั่นเดียวซึ่งเป็นความท้าทายที่สนุกอีกอย่างที่จะช่วยให้เข้าใจธรรมชาติของรหัสที่ง่ายที่สุดและแม้แต่เวลาทำงานก็ไม่ได้เกินความสามารถของใคร
อาจารย์เจมส์

0

ลองอันนี้:

Window.function_exists=function(function_name,scope){
//Setting default scope of none is provided
If(typeof scope === 'undefined') scope=window;
//Checking if function name is defined
If (typeof function_name === 'undefined') throw new 
Error('You have to provide an valid function name!');
//The type container
var fn= (typeof scope[function_name]);
//Function type
If(fn === 'function') return true;
//Function object type
if(fn.indexOf('function')!== false) return true; 
return false;
}

โปรดระวังว่าฉันได้เขียนสิ่งนี้ด้วยมือถือของฉันอาจมีปัญหาตัวพิมพ์ใหญ่และ / หรือการแก้ไขอื่น ๆ ที่จำเป็นเช่นชื่อฟังก์ชั่นตัวอย่าง

หากคุณต้องการฟังก์ชั่นอย่าง PHP เพื่อตรวจสอบว่ามีการตั้งค่า var:

Window.isset=function (variable_con){
If(typeof variable_con !== 'undefined') return true;
return false;
}

0

เพื่อแสดงคำตอบก่อนหน้านี่เป็นตัวอย่างสั้น ๆ ของ JSFiddle:

function test () {
console.log()

}

console.log(typeof test) // >> "function"

// implicit test, in javascript if an entity exist it returns implcitly true unless the element value is false as :
// var test = false
if(test){ console.log(true)}
else{console.log(false)}

// test by the typeof method
if( typeof test === "function"){ console.log(true)}
else{console.log(false)}


// confirm that the test is effective : 
// - entity with false value
var test2 = false
if(test2){ console.log(true)}
else{console.log(false)}

// confirm that the test is effective :
// - typeof entity
if( typeof test ==="foo"){ console.log(true)}
else{console.log(false)}

/* Expected :
function
true 
true 
false
false
*/


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.