জাভাস্ক্রিপ্টে অনন্য বস্তু শনাক্তকারী ier


119

আমার কিছু পরীক্ষা-নিরীক্ষা করা দরকার এবং জাভাস্ক্রিপ্টে থাকা সামগ্রীর জন্য আমাকে এক ধরণের অনন্য শনাক্তকারী জানতে হবে, তাই আমি দেখতে পাচ্ছি যে সেগুলি একই কিনা। আমি সাম্যতা অপারেটরগুলি ব্যবহার করতে চাই না, পাইথনের আইডি () ফাংশনের মতো আমার দরকার।

এর মতো কিছু আছে কি?


2
আমি কিছুটা কৌতুহলী, আপনি কেন সাম্যতা অপারেটরগুলি এড়াতে চান?
সিএমএস

22
কারণ আমি কিছু সাধারণ চাই, এবং আমি একটি নম্বর দেখতে চাই, কিছু পরিষ্কার। এই ভাষা বিড়ালছানা কাঁদে, আমি ইতিমধ্যে এটি যথেষ্ট যুদ্ধ করছি।
স্টিফানো বোরিনি

4
কঠোর সাম্য অপারেটর (===) আপনি অবজেক্টগুলির জন্য যা চেয়েছিলেন তা করবে (আপনি যদি সংখ্যা / স্ট্রিং / ইত্যাদি তুলনা করেন তবে এটি একই জিনিস নয়), এবং প্রতিটি বস্তুর মধ্যে একটি গোপন অনন্য আইডি তৈরির চেয়ে সহজ।
বেন জোটো

4
@ সিএমএস @ বেনের আইডিসিটি কোনও আইডেন্টিটিসেটের মতো জিনিসগুলি ডিবাগ করতে বা প্রয়োগ করতে কার্যকর হতে পারে।
অ্যালেক্স জেসমিন

9
আমি যোগাযোগ করতে চাই যে আমি জাভাস্ক্রিপ্ট বোঝার ক্ষেত্রে একটি অগ্রগতি করেছি। এক ধরনের সিনপাস বন্ধ। এখন সবকিছু পরিষ্কার। আমি জিনিস দেখেছি। আমি জাভাস্ক্রিপ্ট প্রোগ্রামার মধ্যে একটি স্তর অর্জন।
স্টেফানো বোরিনি

উত্তর:


68

আপডেট আমার নীচের উত্তরটি সময় এবং আমার বোঝার উপযোগী একটি স্টাইলে 6 বছর আগে লেখা হয়েছিল। মন্তব্যে কিছু কথোপকথনের প্রতিক্রিয়া হিসাবে, এটির জন্য আরও আধুনিক পদ্ধতির উপায়টি হল:

(function() {
    if ( typeof Object.id == "undefined" ) {
        var id = 0;

        Object.id = function(o) {
            if ( typeof o.__uniqueid == "undefined" ) {
                Object.defineProperty(o, "__uniqueid", {
                    value: ++id,
                    enumerable: false,
                    // This could go either way, depending on your 
                    // interpretation of what an "id" is
                    writable: false
                });
            }

            return o.__uniqueid;
        };
    }
})();

var obj = { a: 1, b: 1 };

console.log(Object.id(obj));
console.log(Object.id([]));
console.log(Object.id({}));
console.log(Object.id(/./));
console.log(Object.id(function() {}));

for (var k in obj) {
    if (obj.hasOwnProperty(k)) {
        console.log(k);
    }
}
// Logged keys are `a` and `b`

আপনার যদি প্রত্নতাত্ত্বিক ব্রাউজারের প্রয়োজনীয়তা থাকে তবে এর জন্য ব্রাউজারের সামঞ্জস্যের জন্য এখানে চেক করুনObject.defineProperty

মূল উত্তরটি নীচে রাখা হয়েছে (পরিবর্তনের ইতিহাসের পরিবর্তে) কারণ আমি মনে করি তুলনাটি মূল্যবান।


আপনি নিম্নলিখিত একটি স্পিন দিতে পারেন। এটি আপনাকে তার নির্মাতা বা অন্য কোথাও স্পষ্টভাবে কোনও আইটের আইডি সেট করার বিকল্প দেয়।

(function() {
    if ( typeof Object.prototype.uniqueId == "undefined" ) {
        var id = 0;
        Object.prototype.uniqueId = function() {
            if ( typeof this.__uniqueid == "undefined" ) {
                this.__uniqueid = ++id;
            }
            return this.__uniqueid;
        };
    }
})();

var obj1 = {};
var obj2 = new Object();

console.log(obj1.uniqueId());
console.log(obj2.uniqueId());
console.log([].uniqueId());
console.log({}.uniqueId());
console.log(/./.uniqueId());
console.log((function() {}).uniqueId());

আপনি অভ্যন্তরীণভাবে ইউনিক আইডি সংরক্ষণের জন্য যে কোনও সদস্য ব্যবহার করবেন না কেন এটি অন্য কোনও স্বয়ংক্রিয়ভাবে তৈরি সদস্যের নামের সাথে সংঘর্ষ না ঘটে তা নিশ্চিত হয়ে নিন।


1
@ জাস্টিন অবজেক্ট.প্রোটোটাইপগুলিতে বৈশিষ্ট্য যুক্ত করা ECMAScript 3 তে সমস্যাযুক্ত কারণ এই বৈশিষ্ট্যগুলি সমস্ত অবজেক্টে গুনযোগ্য। সুতরাং আপনি যদি অবজেক্ট.প্রোটোটাইপ.এ সংজ্ঞায়িত করেন তবে আপনি " প্রপ in}" সতর্কতা (প্রপ) করার জন্য যখন "এ" দৃশ্যমান হবে ; সুতরাং আপনাকে অবজেক্ট.প্রোটোটাইপ বৃদ্ধিতে এবং একটি ফর লিন ব্যবহার করে রেকর্ডের মাধ্যমে পুনরুক্ত করতে সক্ষম হতে একটি আপস করতে হবে। এটি গ্রন্থাগারগুলির জন্য একটি গুরুতর সমস্যা
অ্যালেক্স জেসমিন

29
কোনও আপস নেই। লুপ object.hasOwnProperty(member)ব্যবহার করার সময় সর্বদা এটি ব্যবহারের জন্য এটি দীর্ঘকালীন একটি অনুশীলন হিসাবে বিবেচিত হয় for..in। এটি একটি ভাল নথিভুক্ত অনুশীলন এবং একটি যা জ্ল্লিন্ট দ্বারা প্রয়োগ করা হয়
জাস্টিন জনসন

3
আমি উভয়ই এটি করার জন্য পুনঃসংশোধন করব না, কমপক্ষে প্রতিটি বস্তুর জন্য নয়, আপনি কেবল যে জিনিসগুলি পরিচালনা করেন তা দিয়ে আপনি একই কাজ করতে পারেন। দুর্ভাগ্যক্রমে বেশিরভাগ সময় আমাদের বাহ্যিক জাভাস্ক্রিপ্ট লাইব্রেরি ব্যবহার করতে হয় এবং দুর্ভাগ্যক্রমে তাদের প্রত্যেকেরই ভাল উন্নতি হয় না তাই আপনার ওয়েব পৃষ্ঠায় অন্তর্ভুক্ত সমস্ত লাইব্রেরির সম্পূর্ণ নিয়ন্ত্রণ না থাকলে আপনি এড়াতে পারেন বা কমপক্ষে আপনি জানেন যে তারা ভাল পরিচালনা করেছেন led ।
অপ্রয়োজনীয়

1
@JustinJohnson আছে: ES5 একটি আপস হল: defineProperty(…, {enumerable:false})। এবং uidপদ্ধতিটি নিজেই যেকোনোভাবে নামস্থানে হওয়া উচিতObject
বার্গি

@ জাস্টিন জনসন যদি বলতে পারেন যে অবজেক্ট আইডিটি 4কেমন ছিল আপনি কীভাবে আইডি 4 এর সাথে একটি ভেরিয়েবলের সাথে আপত্তিটি অর্পণ করবেন যাতে আপনি এটি দিয়ে স্টাফ করতে পারেন ... এর বৈশিষ্ট্যগুলি অ্যাক্সেস করার মতো?
স্যার

50

আমার পর্যবেক্ষণ যতদূর যায়, এখানে পোস্ট করা কোনও উত্তরের অপ্রত্যাশিত পার্শ্ব প্রতিক্রিয়া থাকতে পারে।

ES2015- সামঞ্জস্যপূর্ণ পরিবেশে, আপনি WeakMap ব্যবহার করে কোনও পার্শ্ব প্রতিক্রিয়া এড়াতে পারবেন ।

const id = (() => {
    let currentId = 0;
    const map = new WeakMap();

    return (object) => {
        if (!map.has(object)) {
            map.set(object, ++currentId);
        }

        return map.get(object);
    };
})();

id({}); //=> 1

1
না কেন return currentId?
গস্ট ভ্যান ডি ওয়াল

এর WeakMapবিরোধিতা কেন Map? আপনি যদি কোনও স্ট্রিং বা নম্বর সরবরাহ করেন তবে এই ক্রিয়াটি ক্রাশ হবে।
নেট সিমার

35

সর্বশেষ ব্রাউজারগুলি অবজেক্ট.প্রোটোটাইপ বাড়ানোর জন্য একটি ক্লিনার পদ্ধতি সরবরাহ করে। এই কোডটি সম্পত্তি গণনা থেকে গোপনীয় সম্পত্তি তৈরি করবে (পি ইন ও এর জন্য)

জন্য ব্রাউজারে defineProperty বাস্তবায়ন , আপনি এটির মতো uniqueId সম্পত্তি বাস্তবায়ন করতে পারেন:

(function() {
    var id_counter = 1;
    Object.defineProperty(Object.prototype, "__uniqueId", {
        writable: true
    });
    Object.defineProperty(Object.prototype, "uniqueId", {
        get: function() {
            if (this.__uniqueId == undefined)
                this.__uniqueId = id_counter++;
            return this.__uniqueId;
        }
    });
}());

বিশদগুলির জন্য, https://developer.mozilla.org/en/JavaScript/ উল্লেখ / গ্লোবাল_অবজেক্টস / অবজেক্ট / ডিফাইনপ্রোপার্টি দেখুন


2
"সর্বশেষ ব্রাউজারগুলি" স্পষ্টতই ফায়ারফক্স 3.6 অন্তর্ভুক্ত করে না। (হ্যাঁ আমি Firefox এর নতুন সংস্করণে আপগ্রেড জাতি অনির্বাচন, এবং আমি নিশ্চিত আমি শুধুমাত্র এক নই এছাড়া FF3.6 শুধুমাত্র 1 বছর পুরানো।।)
Bart

7
1 বছর বয়সী এই খেলায় "কেবল" নয়। ওয়েবটি গতিশীলভাবে বিকশিত হয়েছে - এটি একটি ভাল জিনিস। আধুনিক ব্রাউজারগুলিতে এটির অনুমোদনের লক্ষ্যে স্বয়ংক্রিয়ভাবে আপডেটার রয়েছে update
Kos

1
কয়েক বছর পরে, এটি গ্রহণযোগ্য উত্তরের চেয়ে আমার পক্ষে আরও ভাল কাজ করছে বলে মনে হচ্ছে।
ফিটার ম্যান

11

আসলে, আপনাকে objectপ্রোটোটাইপটি পরিবর্তন করতে হবে এবং সেখানে কোনও ক্রিয়াকলাপ যুক্ত করার দরকার নেই। নিম্নলিখিত আপনার উদ্দেশ্য জন্য ভাল কাজ করা উচিত।

var __next_objid=1;
function objectId(obj) {
    if (obj==null) return null;
    if (obj.__obj_id==null) obj.__obj_id=__next_objid++;
    return obj.__obj_id;
}

4
নোকাস, সাপ_কেস এবং উট কেস তিনটিই একটি 6-লাইন কোড স্নিপেটে প্রবেশ করেছে। আপনি প্রতিদিন দেখতে পাচ্ছেন না
গাস্ট ভ্যান ডি ওয়াল

এটি objectহ্যাকের চেয়ে অনেক বেশি দৃinc়প্রত্যয়ী প্রক্রিয়া বলে মনে হচ্ছে । আপনি কেবল তখনই চালনা করতে পারেন যখন আপনি ওপি'র বস্তুর সাথে মিল রাখতে চান এবং এটি বাকি সময় থেকে দূরে থাকে।
জে এল পেয়ারেট

6

Object.defineProperty()পদ্ধতিটি বাস্তবায়নকারী ব্রাউজারগুলির জন্য , নীচের কোডটি এমন কোনও ফাংশন জেনারেট করে এবং ফেরত দেয় যা আপনি নিজের মালিকানাধীন কোনও বস্তুর সাথে আবদ্ধ করতে পারেন।

এই পদ্ধতির না বাড়িয়ে দেওয়ার সুবিধা রয়েছে Object.prototype

প্রদত্ত বস্তুর কোনও __objectID__সম্পত্তি আছে কিনা তা যাচাই করে কোডটি কাজ করে এবং এটি যদি না হয় তবে একটি গোপন (অ-গণনাযোগ্য) কেবল পঠনযোগ্য সম্পত্তি হিসাবে সংজ্ঞায়িত করে কাজ করে।

সুতরাং এটি কেবলমাত্র পঠিত obj.__objectID__সম্পত্তিটি সংজ্ঞায়িত করার পরে পরিবর্তন বা পুনরায় সংজ্ঞায়িত করার যে কোনও প্রয়াসের বিরুদ্ধে নিরাপদ এবং নীরবে ব্যর্থ হওয়ার পরিবর্তে ধারাবাহিকভাবে একটি দুর্দান্ত ত্রুটি ছুঁড়ে দেয়।

অবশেষে, বেশ চরম ক্ষেত্রে যেখানে অন্য কোনও কোড ইতিমধ্যে __objectID__একটি প্রদত্ত বস্তুর উপরে সংজ্ঞা দিয়েছে, এই মানটি কেবল ফিরে আসবে।

var getObjectID = (function () {

    var id = 0;    // Private ID counter

    return function (obj) {

         if(obj.hasOwnProperty("__objectID__")) {
             return obj.__objectID__;

         } else {

             ++id;
             Object.defineProperty(obj, "__objectID__", {

                 /*
                  * Explicitly sets these two attribute values to false,
                  * although they are false by default.
                  */
                 "configurable" : false,
                 "enumerable" :   false,

                 /* 
                  * This closure guarantees that different objects
                  * will not share the same id variable.
                  */
                 "get" : (function (__objectID__) {
                     return function () { return __objectID__; };
                  })(id),

                 "set" : function () {
                     throw new Error("Sorry, but 'obj.__objectID__' is read-only!");
                 }
             });

             return obj.__objectID__;

         }
    };

})();

4

jQuery কোড এর নিজস্ব data()আইডি হিসাবে নিজস্ব পদ্ধতি ব্যবহার করে ।

var id = $.data(object);

ব্যাকস্টেজ পদ্ধতিতে dataএকটি অনন্য আইডির মতো স্ট্রিমের পরবর্তী আইডি objectনামক একটি বিশেষ ক্ষেত্র তৈরি করে"jQuery" + now()

id = elem[ expando ] = ++uuid;

আমি আপনাকে পরামর্শ দিচ্ছি যে আপনি একই পদ্ধতিটি ব্যবহার করবেন যেমন জন রেসিগ স্পষ্টতই জানেন যে জাভাস্ক্রিপ্ট সম্পর্কে যা আছে এবং তাঁর পদ্ধতিটি সমস্ত জ্ঞানের উপর ভিত্তি করে।


5
jQuery এর dataপদ্ধতিতে ত্রুটি রয়েছে। উদাহরণস্বরূপ stackoverflow.com/questions/1915341/… দেখুন । এছাড়াও, জন রেসিগ কোনওভাবেই জাভাস্ক্রিপ্ট সম্পর্কে জানার জন্য সমস্ত কিছু জানেন এবং বিশ্বাস করেন যে তিনি আপনাকে জাভাস্ক্রিপ্ট বিকাশকারী হিসাবে সাহায্য করবেন না।
টিম ডাউন

1
@ টিম, এটি এখানে উপস্থাপন করা অন্য যে কোনও পদ্ধতির মতো অনন্য আইডি পাওয়ার ক্ষেত্রে ততটা ত্রুটি রয়েছে কারণ এটি হুডের নীচে প্রায় একই রকম হয়। এবং হ্যাঁ, আমি বিশ্বাস করি জন রেসিগ আমার চেয়ে অনেক বেশি জানেন এবং তিনি ডগলাস ক্রকফোর্ড না হলেও তার সিদ্ধান্তগুলি থেকে আমার শেখা উচিত।
ভাভা

আমি যতদূর জানি $ .data কাজ জাভাস্ক্রিপ্ট বস্তু কিন্তু শুধুমাত্র DOM উপাদানে না।
এমবি 21

4

যে কোনও কী সংঘর্ষ রোধ করতে সিম্বলস ব্যবহার করে @ সমন্বয় জবাবের টাইপস্ক্রিপ্ট সংস্করণ, সুবিধার জন্য গ্লোবাল অবজেক্ট.আইডিতে যুক্ত করা হয়েছে। কেবল নীচের কোডটি পেস্ট করুন, বা এটি আপনি আমদানি করবেন এমন একটি ObjecId.ts ফাইলে রাখুন।

(enableObjectID)();

declare global {
    interface ObjectConstructor {
        id: (object: any) => number;
    }
}

const uniqueId: symbol = Symbol('The unique id of an object');

export function enableObjectID(): void {
    if (typeof Object['id'] !== 'undefined') {
        return;
    }

    let id: number = 0;

    Object['id'] = (object: any) => {
        const hasUniqueId: boolean = !!object[uniqueId];
        if (!hasUniqueId) {
            object[uniqueId] = ++id;
        }

        return object[uniqueId];
    };
}

ব্যবহারের উদাহরণ:

console.log(Object.id(myObject));

1

আমি এই জাতীয় কোড ব্যবহার করেছি, যার ফলে অবজেক্টগুলি অনন্য স্ট্রিংগুলির সাহায্যে স্ট্রিংফাই করবে:

Object.prototype.__defineGetter__('__id__', function () {
    var gid = 0;
    return function(){
        var id = gid++;
        this.__proto__ = {
             __proto__: this.__proto__,
             get __id__(){ return id }
        };
        return id;
    }
}.call() );

Object.prototype.toString = function () {
    return '[Object ' + this.__id__ + ']';
};

__proto__বিট রেখে দেওয়ার জন্য __id__বস্তু দেখানো থেকে সংগ্রহকারী। এটি কেবল ফায়ারফক্সে পরীক্ষা করা হয়েছে।


শুধু মনে রাখবেন যে __defineGetter__এটি মানক নয়।
টোমা জ্যাটো - মনিকা

1

অবজেক্ট.প্রোটোটাইপটি পরিবর্তন না করার পরামর্শ সত্ত্বেও, এটি এখনও সীমিত সুযোগের মধ্যে পরীক্ষার জন্য সত্যই কার্যকর হতে পারে। গৃহীত উত্তরের লেখক এটি পরিবর্তন করেছেন, তবে এখনও সেট Object.idকরে চলেছেন , যা আমার কাছে বোধগম্য নয়। এখানে একটি স্নিপেট রয়েছে যা কাজটি করে:

// Generates a unique, read-only id for an object.
// The _uid is generated for the object the first time it's accessed.

(function() {
  var id = 0;
  Object.defineProperty(Object.prototype, '_uid', {
    // The prototype getter sets up a property on the instance. Because
    // the new instance-prop masks this one, we know this will only ever
    // be called at most once for any given object.
    get: function () {
      Object.defineProperty(this, '_uid', {
        value: id++,
        writable: false,
        enumerable: false,
      });
      return this._uid;
    },
    enumerable: false,
  });
})();

function assert(p) { if (!p) throw Error('Not!'); }
var obj = {};
assert(obj._uid == 0);
assert({}._uid == 1);
assert([]._uid == 2);
assert(obj._uid == 0);  // still

1

আমি একই সমস্যার মুখোমুখি হয়েছি এবং আমি ES6 এর সাথে সমাধানটি এখানে প্রয়োগ করেছি

code
let id = 0; // This is a kind of global variable accessible for every instance 

class Animal {
constructor(name){
this.name = name;
this.id = id++; 
}

foo(){}
 // Executes some cool stuff
}

cat = new Animal("Catty");


console.log(cat.id) // 1 

1

দুটি বস্তুর তুলনা করার উদ্দেশ্যে, এটি করার সহজতম উপায় হ'ল জিনিসগুলির সাথে তুলনা করার সময় যে কোনও একটি বস্তুর সাথে একটি অনন্য সম্পত্তি যুক্ত করা, সম্পত্তি অন্যটিতে উপস্থিত কিনা তা পরীক্ষা করে আবার এটি সরিয়ে ফেলতে হবে। এটি ওভাররাইডিং প্রোটোটাইপগুলি সংরক্ষণ করে।

function isSameObject(objectA, objectB) {
   unique_ref = "unique_id_" + performance.now();
   objectA[unique_ref] = true;
   isSame = objectB.hasOwnProperty(unique_ref);
   delete objectA[unique_ref];
   return isSame;
}

object1 = {something:true};
object2 = {something:true};
object3 = object1;

console.log(isSameObject(object1, object2)); //false
console.log(isSameObject(object1, object3)); //true
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.