"এই" কীওয়ার্ডটি কোনও ফাংশনের মধ্যে কীভাবে কাজ করে?


248

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

এটি স্বেচ্ছাচারী বলে মনে হচ্ছে, যদিও এটি কাজ করার জন্য এটিই আমি আশা করব। এটি কি নির্ধারিত আচরণ? এটি ক্রস ব্রাউজার নিরাপদ? "অনুমানটি তাই বলে" এর বাইরে এটি কেন এ জাতীয় উপায়ের অন্তর্নিহিত কোনও যুক্তি রয়েছে (উদাহরণস্বরূপ, এটি কি কিছু বিস্তৃত নকশার সিদ্ধান্ত / দর্শনের ফলাফল)? পেরড-ডাউন কোড উদাহরণ:

// inside class definition, itself an object literal, we have this function:
onRender: function() {

    this.menuItems = this.menuItems.concat([
        {
            text: 'Group by Module',
            rptletdiv: this
        },
        {
            text: 'Group by Status',
            rptletdiv: this
        }]);
    // etc
}

আমি যখন এটিও করি তখন এটি ঘটে var signup = { onLoadHandler:function(){ console.log(this); return Type.createDelegate(this,this._onLoad); }, _onLoad: function (s, a) { console.log("this",this); }};
ডিপটেকটন্স


খুঁজে বার করো পোস্টটি । এই কীওয়ার্ডটির বিভিন্ন ব্যবহার এবং আচরণের কিছু ভাল ব্যাখ্যা রয়েছে।
হাসিজা প্রেম করুন

এই লিঙ্কটি চেকআউট করুন scotch.io/@alZami/ বোঝাবোধ- এই- জাভাস্ক্রিপ্ট
AL-zami

উত্তর:


558

আমার আর একটি পোস্ট থেকে ন্যাশনালবালাইজড, আপনি এই সম্পর্কে জানতে চেয়েছিলেন এর চেয়ে বেশি এখানে ।

আমি শুরু করার আগে, জাভাস্ক্রিপ্ট সম্পর্কে মনে রাখা এবং এটি যখন বোধগম্য হয় না তখন নিজের কাছে পুনরাবৃত্তি করা সবচেয়ে গুরুত্বপূর্ণ বিষয়। জাভাস্ক্রিপ্ট ক্লাস আছে না (ES6 classহয় অন্বিত চিনি )। কিছু যদি শ্রেণীর মতো লাগে তবে এটি একটি চালাক কৌশল trick জাভাস্ক্রিপ্ট অবজেক্ট এবং ফাংশন রয়েছে । (এটি ১০০% নির্ভুল নয়, ফাংশনগুলি কেবলমাত্র বস্তু, তবে কখনও কখনও এগুলি পৃথক জিনিস হিসাবে ভাবাতে সহায়ক হতে পারে)

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

জাভাস্ক্রিপ্টে ফাংশন চাওয়ার চারটি উপায় রয়েছে। আপনি ফাংশনটি একটি পদ্ধতি হিসাবে, একটি ফাংশন হিসাবে, একজন কনস্ট্রাক্টর হিসাবে এবং প্রয়োগ হিসাবে আবেদন করতে পারেন

একটি পদ্ধতি হিসাবে

একটি পদ্ধতি একটি ফাংশন যা কোনও বস্তুর সাথে সংযুক্ত থাকে

var foo = {};
foo.someMethod = function(){
    alert(this);
}

যখন একটি পদ্ধতি হিসাবে প্রার্থনা, এই বস্তু বাধ্য হবে ফাংশন / পদ্ধতি একটি অংশ। এই উদাহরণে, এটি foo আবদ্ধ হবে will

একটি ফাংশন হিসাবে

যদি আপনার একা স্ট্যান্ড ফাংশন থাকে তবে এই ভেরিয়েবলটি "গ্লোবাল" অবজেক্টের সাথে আবদ্ধ হবে, প্রায়শই ব্রাউজারের প্রসঙ্গে উইন্ডো অবজেক্ট।

 var foo = function(){
    alert(this);
 }
 foo();

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

অনেক লোক সমস্যাটিকে ঘিরে ফেলেন, উম, এই জাতীয় কিছু করে

var foo = {};
foo.someMethod = function (){
    var that=this;
    function bar(){
        alert(that);
    }
}

আপনি একটি পরিবর্তনশীল সংজ্ঞায়িত যে যা পয়েন্ট এই । বন্ধ (ক বিষয় সব নিজের থাকবে) রাখে যে প্রায়, তাই আপনি যদি একটি কলব্যাক যেমন বার কল, এটা এখনও একটি রেফারেন্স আছে।

দ্রষ্টব্য: use strictমোডে যদি ফাংশন হিসাবে ব্যবহৃত হয় তবে thisএটি বিশ্বব্যাপী আবদ্ধ নয়। (এটি হয় undefined)

একজন কনস্ট্রাক্টর হিসাবে

আপনি কনস্ট্রাক্টর হিসাবে কোনও ফাংশনও ডেকে আনতে পারেন। আপনি যে নামকরণ কনভেনশনটি ব্যবহার করছেন (টেস্টবজেক্ট) তার উপর ভিত্তি করে এটি আপনি যা করছেন এবং যা আপনাকে ট্রিপ করছে তা হতে পারে

আপনি নতুন কীওয়ার্ড সহ একটি কনস্ট্রাক্টর হিসাবে কোনও ক্রিয়াকলাপটি শুরু করেন।

function Foo(){
    this.confusing = 'hell yeah';
}
var myObject = new Foo();

যখন কনস্ট্রাক্টর হিসাবে ডাকা হবে তখন একটি নতুন অবজেক্ট তৈরি হবে এবং এটি সেই অবজেক্টের সাথে আবদ্ধ থাকবে। আবার, যদি আপনি ভিতরের ফাংশন আছে এবং তারা callbacks হিসাবে ব্যবহার করছি, আপনি তাদের ফাংশন যেমন invoking হবে এবং এটা এই বিশ্বব্যাপী বস্তু আবদ্ধ করা হবে না। যে var ব্যবহার করুন = এই কৌশল / প্যাটার্ন।

কিছু লোক মনে করেন কনস্ট্রাক্টর / নতুন কীওয়ার্ডটি জাভা / traditionalতিহ্যবাহী ওওপি প্রোগ্রামারগুলিতে ক্লাসগুলির অনুরূপ কিছু তৈরির উপায় হিসাবে একটি হাড় ছিল a

প্রয়োগ পদ্ধতি সহ

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

function foo(a,b){
    alert(a);
    alert(b);
    alert(this);
}
var args = ['ah','be'];
foo.apply('omg',args);

8
দ্রষ্টব্য: কঠোর মোডে , ফাংশন আমন্ত্রণের জন্য thisহবে undefined
দুর্বৃত্ত

1
একটি ফাংশন ঘোষণা, যেমন। ফাংশন মাইফংশন () {}, "পদ্ধতি হিসাবে" একটি বিশেষ ক্ষেত্রে যেখানে "এটি" বিশ্বব্যাপী সুযোগ (উইন্ডো)।
রিচার্ড

1
@রিচার্ড: কঠোর মোড ব্যতীত এবং এর সুযোগের কোনও যোগসূত্র thisনেই। আপনি গ্লোবাল অবজেক্ট মানে ।
টিজে ক্রাউডার

@ অ্যালান-ঝড় "যেমন কনস্ট্রাক্টর" এর this.confusing = 'hell yeah';ক্ষেত্রে একই var confusing = 'hell yeah';? তাহলে দুজনেই অনুমতি দেবে myObject.confusing? আপনি যাতে thisঅভ্যন্তরীণ কাজের জন্য বৈশিষ্ট্য এবং অন্যান্য ভেরিয়েবলগুলি তৈরি করতে ব্যবহার করতে পারেন তা না হলে এটি চমৎকার হবে ।
wunth

কিন্তু তারপর আবার আমি যে কাজ কাপড় ফাংশন এবং কন্সট্রাকটর করার মাধ্যমে গৃহীত মান বাহিরে করা সম্ভব: function Foo(thought){ this.confusing = thought; }এবং তারপরvar myObject = new Foo("hell yeah");
wunth

35

ফাংশন কল

ফাংশনগুলি কেবল এক ধরণের অবজেক্ট।

সমস্ত ফাংশন অবজেক্টের কল এবং প্রয়োগ পদ্ধতি রয়েছে যা তাদের ডাকা হয় এমন ফাংশন অবজেক্টটি কার্যকর করে।

যখন ডাকা হয়, এই পদ্ধতির প্রথম যুক্তিটি thisসেই ফাংশনটি নির্দিষ্ট করে যা ফাংশন সম্পাদনের সময় কীওয়ার্ড দ্বারা রেফারেন্স করা হবে - যদি এটি nullবা undefined, বিশ্বব্যাপী অবজেক্ট window, এর জন্য ব্যবহৃত হয় this

সুতরাং, একটি ফাংশন কল ...

whereAmI = "window";

function foo()
{
    return "this is " + this.whereAmI + " with " + arguments.length + " + arguments";
}

... প্রথম বন্ধনী দিয়ে - foo()- সমতূল্য foo.call(undefined)বা foo.apply(undefined)যা, কার্যকরভাবে হিসাবে একই foo.call(window)বা foo.apply(window)

>>> foo()
"this is window with 0 arguments"
>>> foo.call()
"this is window with 0 arguments"

অতিরিক্ত আর্গুমেন্টটি callফাংশন কলের আর্গুমেন্ট হিসাবে পাস করা হবে, যেখানে একটি অতিরিক্ত অতিরিক্ত আর্গুমেন্ট applyঅ্যারের মতো অবজেক্ট হিসাবে ফাংশন কলের জন্য আর্গুমেন্টগুলি নির্দিষ্ট করতে পারে।

সুতরাং, foo(1, 2, 3)সমতুল্য foo.call(null, 1, 2, 3)বা foo.apply(null, [1, 2, 3])

>>> foo(1, 2, 3)
"this is window with 3 arguments"
>>> foo.apply(null, [1, 2, 3])
"this is window with 3 arguments"

যদি কোনও ফাংশন কোনও অবজেক্টের সম্পত্তি ...

var obj =
{
    whereAmI: "obj",
    foo: foo
};

... অবজেক্টের মাধ্যমে ফাংশনে একটি রেফারেন্স অ্যাক্সেস করা এবং এটিকে প্রথম বন্ধনীর সাথে কল করা - obj.foo()- এর সমতুল্য foo.call(obj)বা হয় foo.apply(obj)

যাইহোক, অবজেক্টের বৈশিষ্ট্য হিসাবে অনুষ্ঠিত ফাংশনগুলি সেই বস্তুর "আবদ্ধ" নয়। আপনি objউপরের সংজ্ঞাটিতে দেখতে পাচ্ছেন যেহেতু ফাংশনগুলি কেবলমাত্র এক ধরণের অবজেক্ট তাই সেগুলি উল্লেখ করা যেতে পারে (এবং এভাবে কোনও ফাংশন কলের রেফারেন্স দিয়ে পাস করা যায় বা কোনও ফাংশন কল থেকে রেফারেন্স দিয়ে ফিরে আসতে পারে)। যখন কোনও ফাংশনের রেফারেন্সটি পাস করা হয়, এটি কোথা থেকে পাস করা হয়েছিল সে সম্পর্কে কোনও অতিরিক্ত তথ্য এটি বহন করে না, যার কারণে নিম্নলিখিতটি ঘটে:

>>> baz = obj.foo;
>>> baz();
"this is window with 0 arguments"

আমাদের ফাংশন রেফারেন্সের bazকল, কলটির জন্য কোনও প্রসঙ্গ সরবরাহ করে না, সুতরাং এটি কার্যকরভাবে একইরকম baz.call(undefined), তাই thisরেফারেন্সিং শেষ হয় window। আমরা যদি bazএটি জানতে চাই যে এটির মালিকানাধীন obj, আমাদের যখন bazআহ্বান করা হয় তখন কোনওভাবে সেই তথ্য সরবরাহ করা দরকার , এটিই যেখানে প্রথম যুক্তিটি callবা applyক্লোজারগুলি কার্যকর হয়।

ব্যাপ্ত শৃঙ্খলা

function bind(func, context)
{
    return function()
    {
        func.apply(context, arguments);
    };
}

যখন কোনও ফাংশন কার্যকর করা হয়, এটি একটি নতুন সুযোগ তৈরি করে এবং কোনও সংযুক্তি সুযোগের একটি রেফারেন্স থাকে। উপরোক্ত উদাহরণে যখন বেনামী ফাংশন তৈরি করা হয়, তখন এটির যে সুযোগটি তৈরি হয়েছিল তার একটি রেফারেন্স থাকে যা bindএর স্কোপ। এটি একটি "বন্ধ" হিসাবে পরিচিত।

[global scope (window)] - whereAmI, foo, obj, baz
    |
    [bind scope] - func, context
        |
        [anonymous scope]

আপনি যখন কোনও ভেরিয়েবলটি অ্যাক্সেস করার চেষ্টা করেন তখন এই "স্কোপ চেইন" প্রদত্ত নামের সাথে একটি ভেরিয়েবল সন্ধান করতে হাঁটতে পারে - যদি বর্তমান স্কোপটিতে ভেরিয়েবলটি না থাকে তবে আপনি শৃঙ্খলে পরবর্তী স্থানটি দেখুন এবং আপনি যতক্ষণ না পৌঁছাবেন ততক্ষণ বৈশ্বিক সুযোগ। বেনামে ফাংশনটি যখন ফিরে আসে এবং bindসম্পাদন শেষ করে, বেনামে ফাংশনটির এখনও তার bindস্কোপের একটি উল্লেখ থাকে , সুতরাং bindএর সুযোগ "দূরে যায় না"।

উপরের সমস্তটি প্রদত্ত আপনি এখন বুঝতে সক্ষম হবেন যে নিম্নোক্ত উদাহরণে স্কোপ কীভাবে কাজ করে এবং যখন একটি নির্দিষ্ট মান সহ "প্রাক-সীমাবদ্ধ" এর কাছাকাছি কোনও ক্রিয়াকলাপটি পাস করার কৌশলটি কেন কাজ thisকরবে তখন:

>>> baz = bind(obj.foo, obj);
>>> baz(1, 2);
"this is obj with 2 arguments"

"যখন কোনও ফাংশনের রেফারেন্সটি পাস করা হয়, এটি কোথা থেকে পাস করা হয়েছিল সে সম্পর্কে কোনও অতিরিক্ত তথ্য বয়ে নেওয়া হয় না" আপনাকে ধন্যবাদ ইনসিন এতে ধন্যবাদ জানায়।
অ্যালেক্স ম্যারাডন

9

এটি কি নির্ধারিত আচরণ? এটি ক্রস ব্রাউজার নিরাপদ?

হ্যাঁ. এবং হ্যাঁ.

কেন এটি এমনভাবে যুক্তিযুক্ত কারণ রয়েছে যা এটি ...

এর অর্থ thisঅনুমান করা বেশ সহজ:

  1. যদি thisকোনও কনস্ট্রাক্টর ফাংশনের অভ্যন্তরে ব্যবহৃত হয়, এবং ফাংশনটি newকীওয়ার্ডের সাহায্যে প্রেরণ করা হয়েছিল , thisতবে তৈরি হওয়া বস্তুটিকে বোঝায়। thisএমনকি সর্বজনীন পদ্ধতিতেও অবজেক্টটির অর্থ বোঝাতে থাকবে।
  2. যদি thisনেস্টেড সুরক্ষিত ফাংশন সহ অন্য কোথাও ব্যবহৃত হয়, তবে এটি বৈশ্বিক সুযোগকে বোঝায় (যা ব্রাউজারের ক্ষেত্রে উইন্ডো অবজেক্ট)।

দ্বিতীয় কেসটি সম্ভবত একটি ডিজাইনের ত্রুটি, তবে ক্লোজার ব্যবহার করে এটির চারপাশে কাজ করা বেশ সহজ।


4

এক্ষেত্রে অভ্যন্তরীণটি বাইরের ফাংশনের thisপরিবর্তকের পরিবর্তে বৈশ্বিক বস্তুর সাথে আবদ্ধ this। ভাষাটি এমনভাবে ডিজাইন করা হয়েছে।

একটি ভাল ব্যাখ্যার জন্য ডগলাস ক্রকফোর্ডের "জাভাস্ক্রিপ্ট: দ্য গুড পার্টস" দেখুন।


4

আমি এটি ECMAScript সম্পর্কে একটি সুন্দর টিউটোরিয়াল পেয়েছি

এই মানটি একটি বিশেষ অবজেক্ট যা এক্সিকিউশন প্রসঙ্গে। অতএব, এটি একটি প্রাসঙ্গিক অবজেক্ট হিসাবে নামকরণ করা যেতে পারে (অর্থাত্ একটি বস্তু যার প্রেক্ষাপটে নির্বাহের প্রসঙ্গটি সক্রিয় করা হয়)।

যে কোনও বস্তু প্রসঙ্গের এই মান হিসাবে ব্যবহার করা যেতে পারে।

এই মানটি কার্যকরকরণ প্রসঙ্গে একটি সম্পত্তি, তবে ভেরিয়েবল অবজেক্টের সম্পত্তি নয়।

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

বৈশ্বিক প্রসঙ্গে, এই মানটি হ'ল গ্লোবাল অবজেক্ট (যার অর্থ এই মানটি এখানে পরিবর্তনশীল বস্তুর সমান)

কোনও ফাংশন প্রসঙ্গে, প্রতিটি একক ফাংশন কলের এই মানটি আলাদা হতে পারে

রেফারেন্স জাভাস্ক্রিপ্ট-কোর এবং অধ্যায়-3-এই


" বৈশ্বিক প্রসঙ্গে, এই মানটি হ'ল গ্লোবাল অবজেক্ট (যার অর্থ, এই মানটি এখানে ভেরিয়েবল অবজেক্টের সমান) "। বিশ্বব্যাপী বস্তু হিসাবে (es4) "পরিবর্তনশীল বস্তুর" এবং ES5 পরিবেশ রেকর্ড, গ্লোবাল সঞ্চালনের প্রসঙ্গের একটি অংশ। তবে এগুলি বৈশ্বিক অবজেক্টের আলাদা আলাদা সত্ত্বা (যেমন পরিবেশের রেকর্ডটি সরাসরি উল্লেখ করা যায় না, এটি অনুমান দ্বারা নিষিদ্ধ করা হয়েছে তবে বৈশ্বিক বস্তু হতে পারে)।
রবিজি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.