জাভাস্ক্রিপ্টে ক্লাস বনাম স্থির পদ্ধতি


261

আমি জানি এটি কাজ করবে:

function Foo() {};
Foo.prototype.talk = function () {
    alert('hello~\n');
};

var a = new Foo;
a.talk(); // 'hello~\n'

তবে আমি যদি ফোন করতে চাই

Foo.talk() // this will not work
Foo.prototype.talk() // this works correctly

আমি Foo.talkকাজ করার কিছু পদ্ধতি খুঁজে পাই ,

  1. Foo.__proto__ = Foo.prototype
  2. Foo.talk = Foo.prototype.talk

এটি করার অন্যান্য উপায় আছে? আমি জানি না এটি করা ঠিক কিনা। আপনি কি আপনার জাভাস্ক্রিপ্ট কোডে শ্রেণি পদ্ধতি বা স্থির পদ্ধতি ব্যবহার করেন?



1
@downvoterstepintothelight Foo.walk = function() {}তার দৃষ্টান্ত প্রভাব হবে না, যেমন প্রোটোটাইপ শৃঙ্খল নেই। ক্রস ব্রাউজারে কোনও ফাংশনকে [[prototype]]নির্দেশ করার উপায় আছে prototypeকি?
lostyzd

3
আপনি কী চান তা সম্ভবত আমার কোনও ধারণা নেই, কারণ শ্রেণি পদ্ধতিগুলি সংজ্ঞা অনুসারে দৃষ্টান্তগুলিকে প্রভাবিত করে না
অকাল অপ্টিমাইজেশন

@ ডাউনভোটারস্টিপিনোথাইলাইট আমি সন্দেহ করি যে পদ্ধতিটি পাইথনের মতো ভাষায় একটি উদাহরণ তার শ্রেণি পদ্ধতিতে কল করতে সক্ষম, পার্থক্যটি thisনির্দেশক।
যাওয়া

উত্তর:


409

প্রথমে মনে রাখবেন যে জাভাস্ক্রিপ্টটি মূলত একটি ক্লাস-ভিত্তিক ভাষা 1 এর পরিবর্তে প্রোটোটাইপাল ভাষাFooকোন শ্রেণি নয়, এটি একটি ফাংশন, যা একটি বস্তু। আপনি কী - ওয়ার্ডটি ব্যবহার করে সেই ফাংশন থেকে কোনও অবজেক্ট ইনস্ট্যান্ট করতে পারেন newযা আপনাকে স্ট্যান্ডার্ড ওওপি ভাষায় শ্রেণীর মতো কিছু তৈরি করতে দেয় allow

আমি __proto__বেশিরভাগ সময় উপেক্ষা করার পরামর্শ দেব কারণ এটিতে ক্রস ব্রাউজারের দুর্বল সমর্থন রয়েছে এবং পরিবর্তে কীভাবে prototypeকাজ করে তা শিখতে মনোনিবেশ করব ।

আপনার যদি কোনও ফাংশন 2 থেকে তৈরি কোনও অবজেক্টের উদাহরণ থাকে এবং আপনি কোনওভাবেই এর সদস্যদের (পদ্ধতি, বৈশিষ্ট্য, বৈশিষ্ট্য, ধ্রুবক ইত্যাদি) অ্যাক্সেস করেন তবে অ্যাক্সেস প্রোটোটাইপ শ্রেণিবদ্ধের নিচে প্রবাহিত হবে যতক্ষণ না এটি (ক) সন্ধান করে সদস্য, বা (খ) অন্য প্রোটোটাইপ খুঁজে পাচ্ছে না।

হায়ারার্কি বলা হয়ে যাওয়া বস্তুর উপরে শুরু হয় এবং তার প্রোটোটাইপ অবজেক্টটি অনুসন্ধান করে। প্রোটোটাইপ অবজেক্টের যদি প্রোটোটাইপ থাকে তবে এটি পুনরাবৃত্তি করে, যদি কোনও প্রোটোটাইপ না থাকে undefinedতবে ফিরে আসে।

উদাহরণ স্বরূপ:

foo = {bar: 'baz'};
console.log(foo.bar); // logs "baz"

foo = {};
console.log(foo.bar); // logs undefined

function Foo(){}
Foo.prototype = {bar: 'baz'};
f = new Foo();
console.log(f.bar);
// logs "baz" because the object f doesn't have an attribute "bar"
// so it checks the prototype
f.bar = 'buzz';
console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set

আমার কাছে দেখে মনে হচ্ছে আপনি ইতিমধ্যে এই "বেসিক" অংশগুলি কমপক্ষে কিছুটা বুঝতে পেরেছেন তবে নিশ্চিত হওয়ার জন্য আমার এগুলি স্পষ্ট করে দেওয়া দরকার।

জাভাস্ক্রিপ্টে, সমস্ত কিছুই একটি অবজেক্ট 3

সব একটা জিনিস।

function Foo(){} কেবল একটি নতুন ফাংশন সংজ্ঞায়িত করে না, এটি একটি নতুন ফাংশন অবজেক্টকে সংজ্ঞায়িত করে যা ব্যবহার করে অ্যাক্সেস করা যায় Foo

এ কারণেই আপনি Fooএর প্রোটোটাইপটি অ্যাক্সেস করতে পারেনFoo.prototype

আপনি যা করতে পারেন তা আরও কার্যকারিতা সেট করে Foo:

Foo.talk = function () {
  alert('hello world!');
};

এই নতুন ফাংশনটি ব্যবহার করে অ্যাক্সেস করা যেতে পারে:

Foo.talk();

আমি আশা করি এতক্ষণে আপনি কোনও ফাংশন অবজেক্ট এবং স্থির পদ্ধতিতে ফাংশনগুলির মধ্যে একটি মিল লক্ষ্য করছেন।

চিন্তা করুন f = new Foo();একটি বর্গ উদাহরণস্বরূপ তৈরি, যেমন Foo.prototype.bar = function(){...}বর্গ জন্য একটি ভাগ পদ্ধতি সংজ্ঞা, এবং Foo.baz = function(){...}বর্গ জন্য একটি পাবলিক স্ট্যাটিক পদ্ধতি সংজ্ঞায়িত করে।


ইসমাস্ক্রিপ্ট ২০১৫ এ ধরণের ঘোষণার জন্য বিভিন্ন ধরণের ঘোষণার জন্য প্রচলিত চিনির প্রচলন করেছে যাতে এগুলি পড়া সহজতর হয়ে ওঠে implement পূর্ববর্তী উদাহরণটি তাই লেখা যেতে পারে:

class Foo {
  bar() {...}

  static baz() {...}
}

যা এই barহিসাবে পরিচিত হতে দেয় :

const f = new Foo()
f.bar()

এবং bazবলা যেতে হবে:

Foo.baz()

1: classECMAScript 5 স্পেসিফিকেশনের একটি "ভবিষ্যত সংরক্ষিত শব্দ" ছিল , তবে ES6 classকীওয়ার্ডটি ব্যবহার করে ক্লাস নির্ধারণের দক্ষতার পরিচয় দেয় ।

2: মূলত কোনও নির্মাণকারীর দ্বারা তৈরি ক্লাসের উদাহরণ, তবে অনেকগুলি নানান পার্থক্য রয়েছে যা আমি আপনাকে বিভ্রান্ত করতে চাই না

3: আদিম মান - যার মধ্যে অন্তর্ভুক্ত undefined,, nullবুলিয়ান, সংখ্যা এবং স্ট্রিংগুলি প্রযুক্তিগতভাবে বস্তু নয় কারণ এগুলি নিম্ন স্তরের ভাষা বাস্তবায়ন। বুলিয়ানস, সংখ্যা এবং স্ট্রিংগুলি প্রোটোটাইপ চেইনের সাথে এখনও ইন্টারঅ্যাক্ট করে যেন তারা বস্তু ছিল, সুতরাং এই উত্তরের উদ্দেশ্যে, তারা যথেষ্ট না হলেও তাদের "অবজেক্ট" বিবেচনা করা আরও সহজ।


1
@ লস্টাইজড - ভাল, তারা এটির মাধ্যমে অ্যাক্সেস করতে পারে Foo.talk()। আপনি চাইলে কনস্ট্রাক্টারে এটি বরাদ্দ করতে পারেন: this.talk = Foo.talk- বা, যেমন আপনি মনে রাখবেন, বরাদ্দ করে Foo.prototype.talk = Foo.talk। তবে আমি নিশ্চিত নই যে এটি একটি ভাল ধারণা - নীতিগতভাবে, উদাহরণ পদ্ধতিগুলি উদাহরণের সাথে নির্দিষ্ট হওয়া উচিত।
nrabinowitz

2
@ ডগ অ্যাভেরি, Foo.talk()কেবল একটি নেমস্পিড ফাংশন কল করছে। আপনি জাভা / সি # এর মতো ওওপি ভাষায় স্থির পদ্ধতিগুলি কীভাবে বলা হয় তার অনুরূপ পরিস্থিতিতে এটি ব্যবহার করবেন। ব্যবহারের ক্ষেত্রে একটি ভাল উদাহরণ যেমন একটি ফাংশন হবে Array.isArray()
zzzzBov

7
পিএস নাল হ'ল অবজেক্ট টাইপ নাল == 'অবজেক্ট'
এমভ্ল্যাডক

1
আপনি যে সমস্ত মূল বিষয়টি মিস করছেন তা হ'ল স্থির পদ্ধতিগুলি উত্তরাধিকার সূত্রে প্রাপ্ত। Foo.talk = function ()...সেখানে নিজস্ব শ্রেণির নাম সাবক্লাসে উপলব্ধ হবে না। এটি "সম্প্রসারিত" সাবক্লাসগুলির সাহায্যে প্রায় কাজ করা যেতে পারে, তবে আমি এখনও আরও মার্জিত উপায় খুঁজছি।

1
@ গণ, কেবল কয়েকটি ভাষাই স্থির পদ্ধতিগুলি উত্তরাধিকার সূত্রে গ্রহণের অনুমতি দেয়। যদি উত্তরাধিকার পছন্দ হয় তবে আপনার শুরু করার জন্য স্থির পদ্ধতি ব্যবহার করা উচিত নয়।
zzzzBov

67

আপনি নীচের হিসাবে এটি অর্জন করতে পারেন:

function Foo() {};

Foo.talk = function() { alert('I am talking.'); };

আপনি এখন নীচের মত "আলাপ" ফাংশন প্রার্থনা করতে পারেন:

Foo.talk();

আপনি এটি করতে পারেন কারণ জাভাস্ক্রিপ্টে, ফাংশনগুলি পাশাপাশি বস্তু are


37

একটি উদাহরণ থেকে একটি স্থির পদ্ধতি কল করুন:

function Clazz() {};
Clazz.staticMethod = function() {
    alert('STATIC!!!');
};

Clazz.prototype.func = function() {
    this.constructor.staticMethod();
}

var obj = new Clazz();
obj.func(); // <- Alert's "STATIC!!!"

সাধারণ জাভাস্ক্রিপ্ট ক্লাস প্রকল্প: https://github.com/reduardo7/sjsClass


13
এটি কোনও স্থির কল নয়। var obj = নতুন ক্লজ (); ক্লাজের একটি নতুন উদাহরণ তৈরি করে । যাইহোক, Clazz.staticMethod () অন্যান্য সমস্ত স্টাফ ছাড়াই ফলাফল অর্জন করে।
এমপেমবার্ন

5
@ এম্বেমবার্ন: এডুয়ার্ডোও তার উত্তরে সঠিক। তিনি আপনাকে যা দেখিয়েছেন তা কেবল আপনি বাইরে থেকে স্থির পদ্ধতিতে কল করতে পারবেন না Clazz.staticMethodতবে কীভাবে কোনও তাত্ক্ষণিক বস্তুর মধ্যে থেকে এই স্থির পদ্ধতির সাথে কীভাবে লিঙ্ক করবেন তা তিনি আপনাকে দেখিয়ে দিচ্ছেন। এটি বিশেষত নোড.জেএস এর মতো viর্ষাপরায়ণগুলিতে কার্যকর যেখানে প্রয়োজন ব্যবহার করে আপনার কাছে আসল নির্মাতাদের সরাসরি অ্যাক্সেস নাও থাকতে পারে। আমি কেবল যুক্ত করবthis.constructor.staticMethod.apply(this, arguments);
মাউভিস লেডফোর্ড

1
একেবারে দুর্দান্ত, এমনকি একটি কফি-স্ক্রিপ্ট constructor: (a) -> @constructor.add @
নির্মাতার ভিতরেও

31

স্থির / দৃষ্টান্তের ভেরিয়েবল এবং পদ্ধতিগুলির সাথে জাভাস্ক্রিপ্ট কীভাবে কাজ করে তা প্রদর্শনের জন্য এখানে একটি ভাল উদাহরণ।

function Animal(name) {
    Animal.count = Animal.count+1||1;// static variables, use function name "Animal"
    this.name = name; //instance variable, using "this"
}

Animal.showCount = function () {//static method
    alert(Animal.count)
}

Animal.prototype.showName=function(){//instance method
    alert(this.name);
}

var mouse = new Animal("Mickey");
var elephant = new Animal("Haddoop");

Animal.showCount();  // static method, count=2
mouse.showName();//instance method, alert "Mickey"
mouse.showCount();//Error!! mouse.showCount is not a function, which is different from  Java

শুভ পয়েন্ট: স্থির ক্রিয়াকলাপের মাধ্যমে অ্যাক্সেস না পাওয়া এই অদ্ভুত হতে পারে this
TrapII

সমাধানের জন্য ধন্যবাদ এটি আমি যা খুঁজছিলাম কী পরিস্থিতিতে thisকীওয়ার্ডের অ্যাক্সেস থাকবে
সান্থোষ

29

সংযোজন ইন, এখন এটা দিয়ে কি করা সম্ভব classএবংstatic

'use strict'

class Foo {
 static talk() {
     console.log('talk')
 };

 speak() {
     console.log('speak')
 };

};

দিতে হবে

var a = new Foo();
Foo.talk();  // 'talk'
a.talk();    // err 'is not a function'
a.speak();   // 'speak'
Foo.speak(); // err 'is not a function'

11

আমি নেমস্পেস ব্যবহার করি:

var Foo = {
     element: document.getElementById("id-here"),

     Talk: function(message) {
            alert("talking..." + message);
     },

     ChangeElement: function() {
            this.element.style.color = "red";
     }
};

এবং এটি ব্যবহার করতে:

Foo.Talk("Testing");

অথবা

Foo.ChangeElement();

6

ES6 এখন কব্জির মতো classএবং staticকীওয়ার্ডগুলিকে সমর্থন করে :

class Foo {
    constructor() {}

    talk() {
        console.log("i am not static");
    }

    static saying() {
        console.log(this.speech);
    }

    static get speech() {
        return "i am static method";
    }

}

আমি এই মত উত্তর খুঁজছিলাম। স্থিতিশীল পদ্ধতিটি কি অ স্থির পদ্ধতি / ভেরিয়েবল কল করতে পারে?
টমাসজ মুলারসিজিক

1
@ টমাসজ স্ট্যাটিক পদ্ধতিতে ক্লাসের কোনও উদাহরণে এটি সেট করা থাকবে না, বরং ক্লাসে নিজেই থাকবে। অবশ্যই, একটি স্থিতিশীল পদ্ধতি একটি উদাহরণ পদ্ধতি কল করতে পারে , তবে কেবল যদি এটির মধ্যে কোনওরকম অ্যাক্সেস থাকে যেমন aticস্ট্যাটিক স্ট্যাটিক মেথড () {নতুন ফু ()। টক (); } ´
জেএইচ এইচ

3

আপনার যদি ES5 তে স্থিতিশীল পদ্ধতিগুলি লিখতে হয় তবে আমি এর জন্য একটি দুর্দান্ত টিউটোরিয়াল পেয়েছি:

//Constructor
var Person = function (name, age){
//private properties
var priv = {};

//Public properties
this.name = name;
this.age = age;

//Public methods
this.sayHi = function(){
    alert('hello');
}
}


// A static method; this method only 
// exists on the class and doesn't exist  
// on child objects
Person.sayName = function() {
   alert("I am a Person object ;)");  
};

দেখুন @ https://abdulapopoola.com/2013/03/30/static-and-instance-methods-in-javascript/


2

শুধু অতিরিক্ত নোট। ES6 ক্লাসটি ব্যবহার করে, যখন আমরা স্থিতিশীল পদ্ধতি তৈরি করি..যে জাভাস্রিপ্ট ইঞ্জিন বর্ণনাকারীটিকে পুরাতন-স্কুল "স্থিতিশীল" পদ্ধতি থেকে আলাদা একটি লিল বিট সেট করে

function Car() {

}

Car.brand = function() {
  console.log('Honda');
}

console.log(
  Object.getOwnPropertyDescriptors(Car)
);

এটি ব্র্যান্ডের () থেকে অভ্যন্তরীণ বৈশিষ্ট্য (বর্ণনাকারী সম্পত্তি) সেট করে

..
brand: [object Object] {
    configurable: true,
    enumerable: true,
    value: ..
    writable: true

}
..

তুলনা করা

class Car2 {
   static brand() {
     console.log('Honda');
   }
}

console.log(
  Object.getOwnPropertyDescriptors(Car2)
);

যা ব্র্যান্ডের () এর অভ্যন্তরীণ বৈশিষ্ট্য নির্ধারণ করে

..
brand: [object Object] {
    configurable: true,
    enumerable: false,
    value:..
    writable: true
  }

..

যে গণনা দেখুন সেট করা হয় মিথ্যা ES6 স্ট্যাটিক পদ্ধতির জন্য।

এর অর্থ আপনি অবজেক্টটি চেক করতে ইন-লুপটি ব্যবহার করতে পারবেন না

for (let prop in Car) {
  console.log(prop); // brand
}

for (let prop in Car2) {
  console.log(prop); // nothing here
}

ES6 এ স্ট্যাটিক পদ্ধতিটিকে অন্য শ্রেণীর ব্যক্তিগত সম্পত্তি (নাম, দৈর্ঘ্য, কনস্ট্রাক্টর) এর মতো বিবেচনা করা হয় তবে স্ট্যাটিক পদ্ধতিটি এখনও লেখার যোগ্য হয় সুতরাং বর্ণনাকারী লিখিতটি সত্য হিসাবে সেট করা থাকে { writable: true }। এর অর্থ হ'ল আমরা এটিকে ওভাররাইড করতে পারি

Car2.brand = function() {
   console.log('Toyota');
};

console.log(
  Car2.brand() // is now changed to toyota
);

1

যখন আপনি কল করতে চেষ্টা Foo.talk, জাতীয় একটি ফাংশন অনুসন্ধান করার চেষ্টা করে talkমাধ্যমে __proto__এবং অবশ্যই, তাই না পাওয়া যেতে পারে।

Foo.__proto__হয় Function.prototype


1

স্ট্যাটিক পদ্ধতি কলগুলি সরাসরি ক্লাসে করা হয় এবং শ্রেণীর উদাহরণগুলিতে কল করা যায় না। স্থির পদ্ধতিগুলি প্রায়শই ইউটিলিটি ফাংশন তৈরি করতে ব্যবহৃত হয়

খুব পরিষ্কার বর্ণনা

সরাসরি mozilla.org থেকে নেওয়া

ফু আপনার ক্লাসে আবদ্ধ হতে হবে তারপরে আপনি যখন একটি নতুন উদাহরণ তৈরি করবেন তখন আপনি myNewInstance.foo কল করতে পারবেন () আপনি যদি নিজের ক্লাস আমদানি করেন তবে আপনি একটি স্থিতিশীল পদ্ধতিতে কল করতে পারেন


0

যখন আমি এইরকম পরিস্থিতির মুখোমুখি হয়েছি তখন আমি এরকম কিছু করেছি:

Logger = {
    info: function (message, tag) {
        var fullMessage = '';        
        fullMessage = this._getFormatedMessage(message, tag);
        if (loggerEnabled) {
            console.log(fullMessage);
        }
    },
    warning: function (message, tag) {
        var fullMessage = '';
        fullMessage = this._getFormatedMessage(message, tag);
        if (loggerEnabled) {
            console.warn(fullMessage);`enter code here`
        }
    },
    _getFormatedMessage: function () {}
};

সুতরাং এখন আমি হিসাবে তথ্য পদ্ধতি কল করতে পারেন Logger.info("my Msg", "Tag");


আমি এটি সর্বদা করি, তবে এটি মূলত কেবল নেমস্পেসিং। এটি আপনাকে উদাহরণস্বরূপ ভার্সন দিয়ে দৃষ্টান্ত তৈরি করতে দেয় না?
dcsan

0

আপনার ক্ষেত্রে, আপনি যদি চান Foo.talk():

function Foo() {};
// But use Foo.talk would be inefficient
Foo.talk = function () {
    alert('hello~\n');
};

Foo.talk(); // 'hello~\n'

তবে এটি প্রয়োগের একটি অদক্ষ উপায়, ব্যবহার prototypeকরা আরও ভাল।


অন্য উপায়, আমার উপায় স্থির শ্রেণি হিসাবে সংজ্ঞায়িত:

var Foo = new function() {
  this.talk = function () {
    alert('hello~\n');
    };
};

Foo.talk(); // 'hello~\n'

উপরের স্থিতিশীল শ্রেণীর ব্যবহারের দরকার নেই prototypeকারণ এটি কেবল স্থির ব্যবহার হিসাবে একবার নির্মিত হবে।

https://github.com/yidas/js-design-patterns/tree/master/class


@jvitoroc ধন্যবাদ!
নিক Tsai

0

জাভাস্ক্রিপ্টের প্রকৃত শ্রেণি নেই বরং এটি প্রোটোটাইপাল উত্তরাধিকারের ব্যবস্থা ব্যবহার করে যাতে বস্তুগুলি তাদের প্রোটোটাইপ শৃঙ্খলের মাধ্যমে অন্যান্য বস্তু থেকে 'উত্তরাধিকারী' হয়। কোডের মাধ্যমেই এটি সর্বোত্তমভাবে ব্যাখ্যা করা হয়েছে:

function Foo() {};
// creates a new function object

Foo.prototype.talk = function () {
    console.log('hello~\n');
};
// put a new function (object) on the prototype (object) of the Foo function object

var a = new Foo;
// When foo is created using the new keyword it automatically has a reference 
// to the prototype property of the Foo function

// We can show this with the following code
console.log(Object.getPrototypeOf(a) === Foo.prototype); 

a.talk(); // 'hello~\n'
// When the talk method is invoked it will first look on the object a for the talk method,
// when this is not present it will look on the prototype of a (i.e. Foo.prototype)

// When you want to call
// Foo.talk();
// this will not work because you haven't put the talk() property on the Foo
// function object. Rather it is located on the prototype property of Foo.

// We could make it work like this:
Foo.sayhi = function () {
    console.log('hello there');
};

Foo.sayhi();
// This works now. However it will not be present on the prototype chain 
// of objects we create out of Foo

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.