2013-12-07 4 views
1

Update здесь является окончательным и рабочий код - только в том случае, если кто-то нашел, что это полезно: jsfiddleПолучить тип объекта

Я написал это как детектор типа. Он работает очень хорошо во всех случаях - насколько я тестировал, но не только в одном случае.

Во-первых, вот фрагмент кода: jsfiddle

var TypeOf = function (thing) { 
    var typeOfThing = typeof thing; 
    if (typeOfThing === 'object') { 
     typeOfThing = Object.prototype.toString.call(thing); 
     if (typeOfThing === '[object Object]') { 
      if (thing.constructor.name) 
       typeOfThing = thing.constructor.name; 
      else if (thing.constructor.toString().charAt(0) === '[') 
       typeOfThing = typeOfThing.substring(8,typeOfThing.length - 1); 
      else 
       typeOfThing = thing.constructor.toString().match(/function\s*(\w+)/)[1]; 
     } else { 
      typeOfThing = typeOfThing.substring(8,typeOfThing.length - 1); 
     } 
     return typeOfThing.toLowerCase(); 
    } else { 
     return typeOfThing; 
    } 
} 

Проблема заключается в том, что если я определить функцию в parse-time тогда он будет работать прекрасно:

function me() {}; 
var you = new me(); 
console.log('Type of you: ' + TypeOf(you)); // me 

Однако, если я просто определить его в run-time, то это не сработает:

var me = function() {}; 
var you = new me(); 
console.log('Type of you: ' + TypeOf(you)); // nope 

Насколько я могу видеть в случае синтаксического разбора constructor что-то вроде function me() {}, поэтому я могу получить его с /function\s*(\w+)/, однако во время выполнения конструктор function() {}.

Есть ли способ заставить это работать? А также есть ли другие случаи, когда этот фрагмент потенциально может не обнаружить тип?

Обновление как указано в комментариях, кажется, что я пытаюсь получить имя анонимной функции. Это выглядит немного страшно для меня. Возможно ли это?

Update, как @jackson сказано ниже, кажется, что правильный вывод должен быть function не me. Это действительно правильно?

+2

Вы по существу спрашиваете, как получить имя анонимной функции. То есть, по определению, довольно сложно сделать. – lonesomeday

+0

@lonesomeday Спасибо, ты прав, я постараюсь перефразировать заголовок вопроса. – Mahdi

+0

Обратите также внимание, что вы можете делать 'thing.constructor.name' в браузерах, которые его поддерживают (! IE, в основном). Кстати, когда я говорю «довольно сложно сделать» выше, я на самом деле имею в виду «по определению невозможно». – lonesomeday

ответ

2

Ваш тест на самом деле преуспела. Тип этой переменной действительно «функция».

Учитывая сопоставление вашего function me() {}; в ваших тестах, вы, кажется, ожидали, что близлежащий тест с слегка модифицированным синтаксисом будет иметь аналогичный результат. Но это не так.Нет причин, по которым you будет иметь «класс» (а не класс) «меня». Это просто обычная старая «функция», не более того.

+0

Hah! Это действительно правильно? ... Позвольте мне добавить его к исходному вопросу! но хороший момент, спасибо! – Mahdi

+0

Да. Думая в терминах C, вы можете считать «я» «указателем» на регулярную функцию. В JavaScript вы просто можете вызвать любую ссылочную функцию, добавив parens к концу переменной, которая ссылается на нее. – Jackson

+0

Еще раз спасибо за ваши усилия :) – Mahdi

1

Тип конструктора этой переменной is a function, а не me. Во втором примере используется анонимная функция, на которую ссылается переменная с именем me.

Подумайте о том, что произойдет, если вы переназначить me к другому объекту:

var me = function() {}; 
var you = new me(); 
me = 10; 
//what if TypeOf(you) had returned me? that would be confusing, because me is now an integer 

Если вы заботитесь об имени переменной, которая хранится анонимную функцию (которая является хрупким, что нужно сделать для вышеупомянутая причина), вы можете использовать это обходное решение.

Это найти имя переменной в глобальной что в настоящее время содержит ссылку на конструктор объекта:

function checkForAnAnonymousConstructor(o) { 
    for(var f in window) { 
     if(window[f] == o.constructor) return f;  
    } 
} 

me = function() { } 
var you = new me(); 
console.log(checkForAnAnonymousConstructor(you)); //-> me 

//This only works whilst the reference is current 
me = 10 
console.log(checkForAnAnonymousConstructor(you));// -> undefined 

http://jsfiddle.net/nE9eP/2

+0

Я надеюсь, что будет обходное решение ...: \ – Mahdi

+0

См. Мое редактирование для возможного обходного пути – joews

+0

Ницца, спасибо за усилия. Я подожду еще немного, чтобы узнать, есть ли у меня больше ответов! У Джексона действительно была хорошая точка ... – Mahdi

0

Вы должны рассмотреть очень важный момент в отношении функций JavaScript, который вы определяете. когда вы делаете var me = function() {}, вы действительно создали анонимную функцию, функцию без какого-либо имени, а затем назначили ее переменной. при создании функции, как это:

function myfunc(){} 

это на самом деле нравится:

var myfunc = function myfunc(){}; 

самый важный момент, имя функции является не уникальным, вы можете создать несколько функций с одним именем ,

var Func1 = function myfuncname(){ this.name = 'Func1'; }; 

или

var Func2 = function myfuncname(){ this.name = 'Func2'; }; 

, как вы видите, здесь мы имеем 2 различные функции, которые, если вы используете TypeOf функцию, результат тот же:

TypeOf(new Func1) -> myfuncname 

, а также

TypeOf(new Func2) -> myfuncname 

Кстати, ваша TypeOf функция совершенно правильно, но единственная проблема здесь, если вы хотите, чтобы получить правильный результат, вы должны изменить:

var me = function() {}; 
var you = new me(); 
console.log('Type of you: ' + TypeOf(you)); 

к:

var me = function me() {}; 
var you = new me(); 
console.log('Type of you: ' + TypeOf(you)); 

Я прошел через это перед вами была трудная задача, и я был бы рад поделиться всем, что вам нужно.

+0

Ну, вы как-то правы, но сначала вы не должны указывать имя анонимным функциям, которые, как мне кажется, похожи на 'mufuncname()', это избыточно и, вероятно, запутывает, и даже если вы хочу сделать это, тогда вы не должны придумывать одно и то же имя для двух разных функций. Но спасибо в любом случае за хедз-ап :) – Mahdi

+0

Для меня результат 'TypeOf (Func1)' и 'TypeOf (Func2)' был «функцией» для каждого. http://jsfiddle.net/9fsqy/1/. – Jackson

+0

Кроме того, имена функций в именованных функциональных выражениях доступны только в пределах объема указанных функций. См. Третий блок кода в этом ответе: http://stackoverflow.com/a/338053/1468130 – Jackson

Смежные вопросы