ฉันสร้างวัตถุ JavaScript แต่ฉันจะกำหนดคลาสของวัตถุนั้นได้อย่างไร
ฉันต้องการบางสิ่งที่คล้ายกับ.getClass()
วิธีของ Java
class
ประเภท มันจะมีclass
คำหลักและไวยากรณ์สำหรับการสร้างต้นแบบที่วิธีการที่สามารถเข้าถึงได้ง่ายมากขึ้นclass
super
ฉันสร้างวัตถุ JavaScript แต่ฉันจะกำหนดคลาสของวัตถุนั้นได้อย่างไร
ฉันต้องการบางสิ่งที่คล้ายกับ.getClass()
วิธีของ Java
class
ประเภท มันจะมีclass
คำหลักและไวยากรณ์สำหรับการสร้างต้นแบบที่วิธีการที่สามารถเข้าถึงได้ง่ายมากขึ้นclass
super
คำตอบ:
ไม่มีคู่แน่นอนที่จะเป็นของ Java getClass()
ใน JavaScript ส่วนใหญ่ว่าเนื่องจากเป็นจาวาสคริปต์ภาษาต้นแบบที่ใช้เมื่อเทียบกับ Java เป็นระดับที่ใช้อย่างใดอย่างหนึ่ง
getClass()
JavaScript มีตัวเลือกหลายอย่างขึ้นอยู่กับสิ่งที่คุณต้องการ:
typeof
instanceof
obj.
constructor
func.
prototype
, proto
.isPrototypeOf
ตัวอย่างบางส่วน:
function Foo() {}
var foo = new Foo();
typeof Foo; // == "function"
typeof foo; // == "object"
foo instanceof Foo; // == true
foo.constructor.name; // == "Foo"
Foo.name // == "Foo"
Foo.prototype.isPrototypeOf(foo); // == true
Foo.prototype.bar = function (x) {return x+x;};
foo.bar(21); // == 42
หมายเหตุ: หากคุณกำลังรวบรวมรหัสของคุณด้วย Uglify มันจะเปลี่ยนชื่อคลาสที่ไม่ใช่สากล เพื่อป้องกันการนี้ทำให้น่าเกลียดมี--mangle
พารามิเตอร์ที่คุณสามารถตั้งค่าเป็นเท็จจะใช้อึกหรือทำเสียงฮึดฮัด
func.prototype
(ใช่ฟังก์ชั่นเป็นวัตถุ แต่prototype
คุณสมบัติมีความเกี่ยวข้องเฉพาะกับฟังก์ชั่นวัตถุ)
instanceof
/ isPrototypeOf()
และที่ไม่ได้มาตรฐาน__proto__
Object.getPrototypeOf()
constructor.name
หากโค้ดของคุณถูกย่อขนาด ชื่อฟังก์ชั่นกำลังจะเปลี่ยนไปโดยพลการ
construction.name
เป็นโทเค็นที่จะถูกละเว้น / ไม่ย่อเล็กสุด นอกจากนี้ซอฟต์แวร์ตัวขยายส่วนใหญ่ (ถ้าไม่ใช่ทั้งหมด) ยังมีกฎข้อยกเว้น
obj.constructor.name
เป็นวิธีการที่เชื่อถือได้ในเบราว์เซอร์ที่ทันสมัย Function.name
ได้รับการเพิ่มอย่างเป็นทางการในมาตรฐานใน ES6 ทำให้นี่เป็นวิธีที่ได้มาตรฐานในการรับ "class" ของวัตถุ JavaScript เป็นสตริง ถ้าวัตถุนั้นถูกสร้างด้วยvar obj = new MyClass()
มันจะส่งคืน "MyClass"
มันจะคืนค่า "Number" สำหรับตัวเลข "Array" สำหรับ Array และ "Function" สำหรับฟังก์ชั่น ฯลฯ โดยทั่วไปจะทำงานได้ตามปกติ เฉพาะกรณีที่มันล้มเหลวคือถ้าวัตถุถูกสร้างขึ้นโดยไม่มีต้นแบบผ่านObject.create( null )
หรือวัตถุถูกยกตัวอย่างจากฟังก์ชั่นที่กำหนดโดยไม่ระบุชื่อ (ไม่มีชื่อ)
โปรดทราบว่าหากคุณกำลังลดขนาดโค้ดของคุณคุณไม่ควรเปรียบเทียบกับสตริงประเภทที่มีการกำหนดรหัสยาก ยกตัวอย่างเช่นแทนการตรวจสอบถ้าแทนที่จะตรวจสอบobj.constructor.name == "MyType"
obj.constructor.name == MyType.name
หรือเพียงเปรียบเทียบตัวสร้างเอง แต่สิ่งนี้จะไม่ทำงานข้ามขอบเขต DOM เนื่องจากมีอินสแตนซ์ที่แตกต่างกันของฟังก์ชันตัวสร้างในแต่ละ DOM ดังนั้นการเปรียบเทียบวัตถุบนตัวสร้างจะไม่ทำงาน
Function.name
ยังไม่ได้เป็นส่วนหนึ่งของมาตรฐาน JavaScript ขณะนี้รองรับ Chrome และ Firefox แต่ไม่รองรับ IE (10)
obj.constructor.name
ใช้ได้กับฟังก์ชั่นที่ตั้งชื่อเท่านั้น เช่นถ้าฉันกำหนดvar Foo = function() {}
แล้วสำหรับvar foo = new Foo()
, foo.constructor.name
จะทำให้คุณสตริงที่ว่างเปล่า
constructor.name
หากโค้ดของคุณถูกย่อขนาด ชื่อฟังก์ชั่นกำลังจะเปลี่ยนไปโดยพลการ
constructor.name
พฤติกรรมจะเป็นไปตามที่คาดไว้ด้วยการสนับสนุนคลาสใหม่ใน ES6
ฟังก์ชันนี้ส่งคืน"Undefined"
ค่าที่ไม่ได้กำหนดและ"Null"
ค่าว่าง
สำหรับค่าอื่น ๆ ทุกCLASSNAME
-part สกัดจากซึ่งเป็นผลมาจากการใช้[object CLASSNAME]
Object.prototype.toString.call(value)
function getClass(obj) {
if (typeof obj === "undefined") return "Undefined";
if (obj === null) return "Null";
return Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
}
getClass("") === "String";
getClass(true) === "Boolean";
getClass(0) === "Number";
getClass([]) === "Array";
getClass({}) === "Object";
getClass(null) === "Null";
// etc...
"Object"
หากคุณมีชนิดของการถ่ายทอดทางพันธุกรรมบางอย่างไปคุณก็จะได้รับ
return obj.constructor.name
ใช่บรรทัดสุดท้ายของการทำงานก็ควรจะเป็น ที่ให้ผลลัพธ์เดียวกันรวมทั้งจัดการกับวัตถุที่ไม่ใช่ของพื้นเมือง
ในการรับ "คลาสหลอก" คุณสามารถรับฟังก์ชัน Constructor ได้โดย
obj.constructor
สมมติว่าconstructor
มีการตั้งค่าอย่างถูกต้องเมื่อคุณทำการรับมรดก - ซึ่งเป็นโดยสิ่งที่ชอบ:
Dog.prototype = new Animal();
Dog.prototype.constructor = Dog;
และทั้งสองบรรทัดพร้อมกับ:
var woofie = new Dog()
จะทำให้ชี้ไปที่woofie.constructor
Dog
โปรดทราบว่าDog
เป็นฟังก์ชั่นการสร้างและเป็นFunction
วัตถุ if (woofie.constructor === Dog) { ... }
แต่คุณสามารถทำ
หากคุณต้องการรับชื่อคลาสเป็นสตริงฉันพบว่าทำงานได้ดีดังต่อไปนี้:
http://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objects
function getObjectClass(obj) {
if (obj && obj.constructor && obj.constructor.toString) {
var arr = obj.constructor.toString().match(
/function\s*(\w+)/);
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
}
มันจะได้รับฟังก์ชั่นคอนสตรัคแปลงเป็นสตริงและแยกชื่อของฟังก์ชั่นคอนสตรัค
โปรดทราบว่าobj.constructor.name
อาจทำงานได้ดี แต่ไม่ได้มาตรฐาน มันอยู่ใน Chrome และ Firefox แต่ไม่ใช่ใน IE รวมถึง IE 9 หรือ IE 10 RTM
คุณสามารถรับการอ้างอิงถึงฟังก์ชั่นคอนสตรัคซึ่งสร้างวัตถุโดยใช้คุณสมบัติคอนสตรัค :
function MyObject(){
}
var obj = new MyObject();
obj.constructor; // MyObject
หากคุณต้องการยืนยันประเภทของวัตถุที่รันไทม์คุณสามารถใช้ตัวดำเนินการinstanceof :
obj instanceof MyObject // true
เพื่อให้สอดคล้องกับบันทึกที่ไม่สามารถย้อนกลับได้ของความเข้ากันได้ย้อนหลัง ECMAScript 6, JavaScript ยังไม่มีclass
ประเภท (แม้ว่าทุกคนจะไม่เข้าใจสิ่งนี้) มันจะมีclass
คำหลักที่เป็นส่วนหนึ่งของclass
ไวยากรณ์สำหรับการสร้างต้นแบบ แต่ยังไม่มีสิ่งที่เรียกว่าระดับ JavaScript ไม่ใช่ตอนนี้และไม่เคยเป็นภาษา OOP แบบดั้งเดิมเลย การพูดของ JS ในแง่ของคลาสเป็นเพียงการทำให้เข้าใจผิดหรือเป็นสัญญาณว่ายังไม่ได้สืบทอดมรดกต้นแบบ (เพียงแค่ทำให้มันเป็นจริง)
นั่นหมายความว่าthis.constructor
ยังคงเป็นวิธีที่ดีในการรับconstructor
ฟังก์ชั่นอ้างอิง และthis.constructor.prototype
เป็นวิธีการเข้าถึงต้นแบบนั้นเอง เนื่องจากนี่ไม่ใช่ Java จึงไม่ใช่คลาส มันเป็นวัตถุต้นแบบที่อินสแตนซ์ของคุณยกตัวอย่าง นี่คือตัวอย่างการใช้น้ำตาล syntactic ES6 สำหรับการสร้างห่วงโซ่ต้นแบบ:
class Foo {
get foo () {
console.info(this.constructor, this.constructor.name)
return 'foo'
}
}
class Bar extends Foo {
get foo () {
console.info('[THIS]', this.constructor, this.constructor.name, Object.getOwnPropertyNames(this.constructor.prototype))
console.info('[SUPER]', super.constructor, super.constructor.name, Object.getOwnPropertyNames(super.constructor.prototype))
return `${super.foo} + bar`
}
}
const bar = new Bar()
console.dir(bar.foo)
นี่คือผลลัพธ์ที่ใช้babel-node
:
> $ babel-node ./foo.js ⬡ 6.2.0 [±master ●]
[THIS] [Function: Bar] 'Bar' [ 'constructor', 'foo' ]
[SUPER] [Function: Foo] 'Foo' [ 'constructor', 'foo' ]
[Function: Bar] 'Bar'
'foo + bar'
ที่นั่นคุณมีมัน! ในปี 2559 มีclass
คำหลักใน JavaScript แต่ยังไม่มีประเภทชั้นเรียน this.constructor
เป็นวิธีที่ดีที่สุดในการรับฟังก์ชั่น Constructor this.constructor.prototype
วิธีที่ดีที่สุดในการเข้าถึงตัวต้นแบบ
ฉันมีสถานการณ์ที่ต้องใช้งานทั่วไปตอนนี้และใช้สิ่งนี้:
class Test {
// your class definition
}
nameByType = function(type){
return type.prototype["constructor"]["name"];
};
console.log(nameByType(Test));
นั่นเป็นวิธีเดียวที่ฉันพบเพื่อให้ได้ชื่อคลาสตามประเภทอินพุตหากคุณไม่มีอินสแตนซ์ของวัตถุ
(เขียนใน ES2017)
สัญกรณ์ดอทยังใช้งานได้ดี
console.log(Test.prototype.constructor.name); // returns "Test"
สำหรับ Javascript Classes ใน ES6 คุณสามารถobject.constructor
ใช้ได้ ในคลาสตัวอย่างด้านล่างgetClass()
เมธอดส่งคืนคลาส ES6 ตามที่คุณต้องการ:
var Cat = class {
meow() {
console.log("meow!");
}
getClass() {
return this.constructor;
}
}
var fluffy = new Cat();
...
var AlsoCat = fluffy.getClass();
var ruffles = new AlsoCat();
ruffles.meow(); // "meow!"
หากคุณยกตัวอย่างคลาสจากgetClass
วิธีการตรวจสอบให้แน่ใจว่าคุณห่อในวงเล็บเช่นruffles = new ( fluffy.getClass() )( args... );
ฉันพบการobject.constructor.toString()
ส่งคืน[object objectClass]
ใน IE แทนที่จะfunction objectClass () {}
ส่งคืนใน chome ดังนั้นฉันคิดว่ารหัสในhttp://blog.magnetiq.com/post/514962277/finding-out-class-names-of-javascript-objectsอาจทำงานได้ไม่ดีใน IE.A และฉันแก้ไขรหัสดังนี้:
var getObjectClass = function (obj) {
if (obj && obj.constructor && obj.constructor.toString()) {
/*
* for browsers which have name property in the constructor
* of the object,such as chrome
*/
if(obj.constructor.name) {
return obj.constructor.name;
}
var str = obj.constructor.toString();
/*
* executed if the return of object.constructor.toString() is
* "[object objectClass]"
*/
if(str.charAt(0) == '[')
{
var arr = str.match(/\[\w+\s*(\w+)\]/);
} else {
/*
* executed if the return of object.constructor.toString() is
* "function objectClass () {}"
* for IE Firefox
*/
var arr = str.match(/function\s*(\w+)/);
}
if (arr && arr.length == 2) {
return arr[1];
}
}
return undefined;
};
ในจาวาสคริปต์ไม่มีคลาส แต่ฉันคิดว่าคุณต้องการชื่อคอนสตรัคเตอร์และobj.constructor.toString()
จะบอกสิ่งที่คุณต้องการ
.name
สิ่งที่คุณต้องการจริงๆคือ
.name
ไม่ได้กำหนดไว้แม้ใน IE 9
เห็นด้วยกับ dfa นั่นเป็นเหตุผลว่าทำไมฉันถึงถือว่า prototye เป็นคลาสเมื่อไม่พบชื่อคลาส
นี่คือฟังก์ชั่นที่ได้รับการอัพเกรดของอีไลเกรย์ที่โพสต์โดย Eli Gray เพื่อให้เข้ากับความคิดของฉัน
function what(obj){
if(typeof(obj)==="undefined")return "undefined";
if(obj===null)return "Null";
var res = Object.prototype.toString.call(obj).match(/^\[object\s(.*)\]$/)[1];
if(res==="Object"){
res = obj.constructor.name;
if(typeof(res)!='string' || res.length==0){
if(obj instanceof jQuery)return "jQuery";// jQuery build stranges Objects
if(obj instanceof Array)return "Array";// Array prototype is very sneaky
return "Object";
}
}
return res;
}
หากคุณต้องการไม่เพียง แต่จะได้รับคลาส แต่ยังขยายออกจากการมีเพียงตัวอย่างเขียน:
มามีกัน
class A{
constructor(name){
this.name = name
}
};
const a1 = new A('hello a1');
ดังนั้นการขยาย A ที่มีอินสแตนซ์เท่านั้นใช้:
const a2 = new ((Object.getPrototypeOf(a)).constructor())('hello a2')
// the analog of const a2 = new A()
console.log(a2.name)//'hello a2'
ฉันแนะนำให้ใช้Object.prototype.constructor.name
:
Object.defineProperty(Object.prototype, "getClass", {
value: function() {
return this.constructor.name;
}
});
var x = new DOMParser();
console.log(x.getClass()); // `DOMParser'
var y = new Error("");
console.log(y.getClass()); // `Error'
getClass()
และgetInstance()
คุณสามารถรับการอ้างอิงสำหรับคลาสของวัตถุโดยใช้ this.constructor
คุณสามารถที่จะได้รับการอ้างอิงสำหรับการเรียนของวัตถุโดยใช้
function A() {
this.getClass = function() {
return this.constructor;
}
this.getNewInstance = function() {
return new this.constructor;
}
}
var a = new A();
console.log(a.getClass()); // function A { // etc... }
// you can even:
var b = new (a.getClass());
console.log(b instanceof A); // true
var c = a.getNewInstance();
console.log(c instanceof A); // true
function A() {};
A.getClass = function() {
return this;
}
A.getInstance() {
return new this;
}
this.constructor
?
คุณสามารถทำอะไรเช่นนี้
class Hello {
constructor(){
}
}
function isClass (func) {
return typeof func === 'function' && /^class\s/.test(Function.prototype.toString.call(func))
}
console.log(isClass(Hello))
สิ่งนี้จะบอกคุณว่าอินพุตเป็นคลาสหรือไม่
Javascript เป็นภาษาที่ไม่มีคลาส: ไม่มีคลาสที่กำหนดพฤติกรรมของคลาสแบบสแตติกใน Java JavaScript ใช้ต้นแบบแทนคลาสเพื่อกำหนดคุณสมบัติของวัตถุรวมถึงวิธีการและการสืบทอด มันเป็นไปได้ที่จะจำลองคุณสมบัติตามคลาสด้วยต้นแบบใน JavaScript
class
ประเภท มันจะมีclass
คำหลักและไวยากรณ์สำหรับการสร้างต้นแบบที่วิธีการที่สามารถเข้าถึงได้ง่ายมากขึ้นclass
super
ดูเหมือนว่าจะตอบคำถามแล้ว แต่ OP ต้องการเข้าถึงคลาสและวัตถุเช่นเดียวกับที่เราทำใน Java และคำตอบที่เลือกนั้นไม่เพียงพอ (imho)
ด้วยคำอธิบายต่อไปนี้เราสามารถรับคลาสของวัตถุ (จริง ๆ แล้วเรียกว่าต้นแบบในจาวาสคริปต์)
var arr = new Array('red', 'green', 'blue');
var arr2 = new Array('white', 'black', 'orange');
คุณสามารถเพิ่มคุณสมบัติเช่นนี้:
Object.defineProperty(arr,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
แต่.last
คุณสมบัติจะใช้ได้เฉพาะกับarr
วัตถุ "" ซึ่งได้รับการยกตัวอย่างจากต้นแบบ Array ดังนั้นเพื่อให้.last
คุณสมบัติพร้อมใช้งานสำหรับวัตถุทั้งหมดที่อินสแตนซ์จาก Array prototype เราต้องกำหนด.last
คุณสมบัติสำหรับ Array prototype:
Object.defineProperty(Array.prototype,'last', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
ปัญหาคือคุณต้องรู้ว่าออบเจ็กต์ (ต้นแบบ) ตัวใดเป็นตัวแปร ' arr
' และ ' arr2
'! กล่าวอีกนัยหนึ่งถ้าคุณไม่ทราบประเภทคลาส (ต้นแบบ) ของarr
วัตถุ '' คุณจะไม่สามารถกำหนดคุณสมบัติให้กับพวกเขาได้ ในตัวอย่างข้างต้นเรารู้ว่า arr เป็นอินสแตนซ์ของวัตถุ Array นั่นคือสาเหตุที่เราใช้ Array.prototype เพื่อกำหนดคุณสมบัติสำหรับ Array แต่ถ้าเราไม่รู้คลาส (ต้นแบบ) ของ ' arr
'
Object.defineProperty(arr.__proto__,'last2', {
get: function(){
return this[this.length -1];
}
});
console.log(arr.last) // blue
console.log(arr2.last) // orange
ดังที่คุณเห็นโดยไม่ทราบว่า ' arr
' เป็นอาเรย์เราสามารถเพิ่มคุณสมบัติใหม่เพียงแค่อ้างอิงถึงคลาสของ ' arr
' โดยใช้ ' arr.__proto__
'
เราเข้าถึงต้นแบบของ ' arr
' โดยไม่ทราบว่ามันเป็นตัวอย่างของ Array และฉันคิดว่านั่นคือสิ่งที่ OP ขอ
__proto__
คุณสมบัติจะเลิกและมีเกือบจะไม่มีประโยชน์มากกว่าprototype
ทรัพย์สิน