รับชื่อของวัตถุหรือคลาส


204

มีวิธีแก้ไขปัญหาเพื่อให้ได้ชื่อฟังก์ชันของวัตถุหรือไม่

function alertClassOrObject (o) {
   window.alert(o.objectName); //"myObj" OR "myClass" as a String
}

function myClass () {
   this.foo = function () {
       alertClassOrObject(this);
   }
}

var myObj = new myClass();
myObj.foo();

for (var k in this) {...}- มีข้อมูลเกี่ยวกับการไม่มีหรือclassName ObjectNameเป็นไปได้ไหมที่จะรับหนึ่งในนั้น?


คุณอาจต้องการเห็นสิ่งนี้: stackoverflow.com/questions/789675/…
Sudhir Bastakoti

คำตอบ:


348

รับฟังก์ชั่นการสร้างวัตถุของคุณแล้วตรวจสอบคุณสมบัติชื่อ

myObj.constructor.name

ส่งคืน "myClass"


175
ระวัง! หากคุณกำลังลดขนาด JavaScript ชื่อของนวกรรมิกจะเปลี่ยนไป
เดซิเบล

34
มีประโยชน์ แต่มีข้อแม้อื่น: หากวัตถุของคุณมีโซ่ต้นแบบ(นอกเหนือจากObject) คุณจะได้รับชื่อลิงค์แรกในโซ่นั้นไม่ใช่ชื่อของนวกรรมิกที่ใช้สร้างวัตถุ ใช้ตัวอย่างต่อไปนี้: function Daddy() {}; function Me() {}; Me.prototype = new Daddy; me = new Me;. me.constructor.nameแล้วโดยไม่คาดคิดผลตอบแทนไม่ได้'Daddy' 'Me'
mklement0

7
และควรรู้ด้วยเช่นกันว่าคุณสมบัติของชื่อไม่ได้รับการสนับสนุนใน <IE9
Jason

10
var Foo = function() {};และสิ่งนี้จะกลับสตริงที่ว่างเปล่าถ้าใช้บนวัตถุประกาศผ่านตัวแปร:
Aleksandr Makov

3
คอนโซล Chrome รู้บางสิ่งที่คุณไม่ชอบ: > myclass=(function(){}); new myclassพิมพ์myclass {}
Hugh Allen

26

ตัวอย่าง:

function Foo () { console.log('Foo function'); }
var Bar = function () { console.log('Bar function'); };
var Abc = function Xyz() { console.log('Abc function'); };

var f = new Foo();
var b = new Bar();
var a = new Abc();

console.log('f', f.constructor.name); // -> "Foo"
console.log('b', b.constructor.name); // -> "Function"
console.log('a', a.constructor.name); // -> "Xyz"


ดูเหมือนว่าเมื่อใช้รูปแบบโมดูลที่เปิดเผยคุณจะได้รับ "วัตถุ" เสมอ function Foo() { return {'foo':'bar'} }; var f = new Foo(); :(
แบรดเคนต์

5

ถ้าคุณใช้ IIFE มาตรฐาน (เช่นกับ TypeScript)

var Zamboch;
(function (_Zamboch) {
    (function (Web) {
        (function (Common) {
            var App = (function () {
                function App() {
                }
                App.prototype.hello = function () {
                    console.log('Hello App');
                };
                return App;
            })();
            Common.App = App;
        })(Web.Common || (Web.Common = {}));
        var Common = Web.Common;
    })(_Zamboch.Web || (_Zamboch.Web = {}));
    var Web = _Zamboch.Web;
})(Zamboch || (Zamboch = {}));

คุณสามารถใส่คำอธิบายประกอบต้นแบบไว้ล่วงหน้าด้วย

setupReflection(Zamboch, 'Zamboch', 'Zamboch');

จากนั้นใช้ฟิลด์ _fullname และ _classname

var app=new Zamboch.Web.Common.App();
console.log(app._fullname);

ฟังก์ชั่นคำอธิบายประกอบที่นี่:

function setupReflection(ns, fullname, name) {
    // I have only classes and namespaces starting with capital letter
    if (name[0] >= 'A' && name[0] &lt;= 'Z') {
        var type = typeof ns;
        if (type == 'object') {
            ns._refmark = ns._refmark || 0;
            ns._fullname = fullname;
            var keys = Object.keys(ns);
            if (keys.length != ns._refmark) {
                // set marker to avoid recusion, just in case 
                ns._refmark = keys.length;
                for (var nested in ns) {
                    var nestedvalue = ns[nested];
                    setupReflection(nestedvalue, fullname + '.' + nested, nested);
                }
            }
        } else if (type == 'function' && ns.prototype) {
            ns._fullname = fullname;
            ns._classname = name;
            ns.prototype._fullname = fullname;
            ns.prototype._classname = name;
        }
    }
}

JsFiddle


4

ตามที่ได้รับคำตอบไปแล้วฉันแค่ต้องการชี้ให้เห็นถึงความแตกต่างในวิธีการรับตัวสร้างของวัตถุใน JavaScript มีความแตกต่างระหว่างตัวสร้างและชื่อวัตถุ / คลาสจริง instanceofถ้าต่อไปจะเพิ่มความซับซ้อนของการตัดสินใจของคุณแล้วบางทีคุณอาจกำลังมองหา หรือบางทีคุณควรถามตัวเองว่า "ทำไมฉันถึงทำอย่างนี้จริง ๆ นี่คือสิ่งที่ฉันพยายามจะแก้ไขหรือไม่?"

หมายเหตุ:

obj.constructor.nameไม่สามารถใช้ได้ในเบราว์เซอร์รุ่นเก่า การจับ(\w+)คู่ควรตอบสนองสไตล์คลาส ES6

รหัส:

var what = function(obj) {
  return obj.toString().match(/ (\w+)/)[1];
};

var p;

// Normal obj with constructor.
function Entity() {}
p = new Entity();
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p));

// Obj with prototype overriden.
function Player() { console.warn('Player constructor called.'); }
Player.prototype = new Entity();
p = new Player();
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p));

// Obj with constructor property overriden.
function OtherPlayer() { console.warn('OtherPlayer constructor called.'); }
OtherPlayer.constructor = new Player();
p = new OtherPlayer();
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p));

// Anonymous function obj.
p = new Function("");
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p));

// No constructor here.
p = {};
console.log("constructor:", what(p.constructor), "name:", p.constructor.name, "class:", what(p));

// ES6 class.
class NPC { 
  constructor() {
  }
}
p = new NPC();
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p));

// ES6 class extended
class Boss extends NPC {
  constructor() {
    super();
  }
}
p = new Boss();
console.log("constructor:", what(p.constructor), "name:", p.constructor.name , "class:", what(p));

ผลลัพธ์:

ป้อนคำอธิบายรูปภาพที่นี่

รหัส: https://jsbin.com/wikiji/edit?js,console


3

ฉันกำลังเผชิญกับปัญหาที่คล้ายกันและไม่มีวิธีแก้ไขปัญหาใดที่นำเสนอที่นี่เหมาะสมที่สุดสำหรับสิ่งที่ฉันกำลังทำอยู่ สิ่งที่ฉันมีคือชุดของฟังก์ชั่นเพื่อแสดงเนื้อหาใน modal และฉันพยายาม refactor มันภายใต้นิยามวัตถุเดียวที่ทำให้ฟังก์ชั่นวิธีการของชั้นเรียน ปัญหาเกิดขึ้นเมื่อฉันพบวิธีใดวิธีหนึ่งที่สร้างปุ่มนำทางบางอย่างภายในโมดอลซึ่งใช้ onClick กับหนึ่งในฟังก์ชั่น - ตอนนี้เป็นวัตถุของคลาส ฉันได้พิจารณาวิธีการอื่น (และยังคงพิจารณาอยู่) เพื่อจัดการกับปุ่ม nav เหล่านี้ แต่ฉันสามารถค้นหาชื่อตัวแปรสำหรับคลาสได้ด้วยการกวาดตัวแปรที่กำหนดในหน้าต่างพาเรนต์ สิ่งที่ฉันทำคือค้นหาสิ่งที่ตรงกับ 'อินสแตนซ์' ของชั้นเรียนของฉันและในกรณีที่อาจมีมากกว่าหนึ่ง

var myClass = function(varName)
{
    this.instanceName = ((varName != null) && (typeof(varName) == 'string') && (varName != '')) ? varName : null;

    /**
     * caching autosweep of window to try to find this instance's variable name
     **/
    this.getInstanceName = function() {
        if(this.instanceName == null)
        {
            for(z in window) {
                if((window[z] instanceof myClass) && (window[z].uniqueProperty === this.uniqueProperty)) {
                    this.instanceName = z;
                    break;
                }
            }
        }
        return this.instanceName;
    }
}

1

ลองสิ่งนี้:

var classname = ("" + obj.constructor).split("function ")[1].split("(")[0];

1
มีกรณีใดบ้างที่สิ่งนี้จะแม่นยำกว่า obj.constructor.name? ฉันไม่เห็นเหตุผลใด ๆ สำหรับความซับซ้อนนี้
JHH

1

ทุกอย่างที่เราต้องการ:

  1. ตัดค่าคงที่ในฟังก์ชัน (โดยที่ชื่อของฟังก์ชันเท่ากับชื่อของวัตถุที่เราต้องการรับ)
  2. ใช้ฟังก์ชั่นลูกศรภายในวัตถุ

console.clear();
function App(){ // name of my constant is App
  return {
  a: {
    b: {
      c: ()=>{ // very important here, use arrow function 
        console.log(this.constructor.name)
      }
    }
  }
}
}
const obj = new App(); // usage

obj.a.b.c(); // App

// usage with react props etc, 
// For instance, we want to pass this callback to some component

const myComponent = {};
myComponent.customProps = obj.a.b.c;
myComponent.customProps(); // App

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