জাভাস্ক্রিপ্ট "এই" পয়েন্টার নেস্ট ফাংশন মধ্যে


97

নেস্টেড ফাংশন দৃশ্যে "এই" পয়েন্টারটি কীভাবে আচরণ করা হয় সে সম্পর্কে আমার একটি প্রশ্ন রয়েছে।

বলুন যে আমি এই ওয়েবপৃষ্ঠায় নিম্নলিখিত নমুনা কোডটি .োকান। আমি নেস্টেড ফাংশনটিকে "doSomeEffects ()" বললে আমি একটি ত্রুটি পাই। আমি ফায়ারবগে চেক করেছি এবং এটি সূচিত করে যে আমি যখন n নেস্টেড ফাংশনে থাকি তখন "এই" পয়েন্টারটি আসলে বিশ্বব্যাপী "উইন্ডো" অবজেক্টের দিকে ইঙ্গিত করে - যা আমি আশা করি না। আমি অবশ্যই কিছু সঠিকভাবে বুঝতে পারছি না কারণ আমি ভেবেছিলাম যেহেতু আমি বস্তুর কোনও ফাংশনের মধ্যে নেস্টেড ফাংশনটি ঘোষণা করেছি, ফাংশনের সাথে এটির "স্থানীয়" সুযোগ থাকা উচিত (অর্থাত "" এই "পয়েন্টারটি বস্তুটির মতোই উল্লেখ করবে) এটি আমার প্রথম "যদি" বিবৃতিতে কীভাবে থাকে)।

যে কোনও পয়েন্টার (কোনও পাং উদ্দেশ্যে নয়) প্রশংসা করা হবে।

var std_obj = {
  options : { rows: 0, cols: 0 },
  activeEffect : "none",
  displayMe : function() {

    // the 'this' pointer is referring to the std_obj
    if (this.activeEffect=="fade") { }

    var doSomeEffects = function() {

      // the 'this' pointer is referring to the window obj, why?
      if (this.activeEffect=="fade") { }

    }

    doSomeEffects();   
  }
};

std_obj.displayMe();

ঠিক আপনার প্রশ্ন কি ?
সরফরাজ

4
যখন কোনও ফাংশনের অভ্যন্তরে ব্যবহৃত হয়, তখন thisসেই বস্তুকে বোঝায় যেখানে ফাংশনটি চাওয়া হয়।
আনুমানিক

9
আপনি বাহ্যিক স্কোপটিতে যা করতে পারতেন তা হ'ল এমন কিছু var self = this;এবং তারপরে selfবন্ধের মাধ্যমে অভ্যন্তরীণ ফাংশনটি উল্লেখ করুন।
কাই

4
doSomeEffectsবিশেষত কোনও আপত্তিটির সাথে সম্পর্কিত নয়, তাই thisএটি উইন্ডো হিসাবে ধরে নেওয়া হয়, সমস্ত উপাদানগুলির মা।
আনুমানিক 5

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

উত্তর:


121

জাভাস্ক্রিপ্টে thisবস্তুটি কীভাবে আপনি আপনার ফাংশন কল করবেন তার উপর ভিত্তি করে।

সাধারণভাবে thisঅবজেক্টটি সেটআপ করার জন্য তিনটি উপায় রয়েছে :

  1. someThing.someFunction(arg1, arg2, argN)
  2. someFunction.call(someThing, arg1, arg2, argN)
  3. someFunction.apply(someThing, [arg1, arg2, argN])

উপরের সমস্ত উদাহরণে thisবস্তুটি হবে someThing। শীর্ষস্থানীয় প্যারেন্ট অবজেক্ট ব্যতীত কোনও ফাংশন কল করার ফলে আপনি সাধারণত বিশ্বব্যাপী অবজেক্টটি পাবেন যা বেশিরভাগ ব্রাউজারে windowঅবজেক্টটি বোঝায় ।


আমি this.doSomeEffects();আপনার উত্তরের উপর ভিত্তি করে কোডটি পরিবর্তন করেছি তবে এখনও এটি কার্যকর হয় না। কেন?
আরশসফট

4
@Arashsoft thisমধ্যে this.doSomeEffects()পয়েন্ট std_obj। উপরের উত্তরে বর্ণিত হিসাবে যদি কোনও ফাংশনে অবজেক্ট রেফারেন্স না থাকে তবে এটি thisউইন্ডো অবজেক্ট হতে লাগে ।
শিবাম

45

যেহেতু এটি এর ধরণের সর্বাধিক উত্সাহিত প্রশ্নগুলির মধ্যে উপস্থিত রয়েছে, তাই এই সমস্ত বছর পরে, তীর ফাংশনগুলি ব্যবহার করে ES6 সমাধানটি যুক্ত করুন:

var std_obj = {
  ...
  displayMe() {
    ...
    var doSomeEffects = () => {
                        ^^^^^^^    ARROW FUNCTION    
      // In an arrow function, the 'this' pointer is interpreted lexically,
      // so it will refer to the object as desired.
      if (this.activeEffect=="fade") { }
    };
    ...    
  }
};

6
এখন সেই অগ্রগতি!
জোশুয়া পিন্টার

দুর্দান্ত, সহজ, সমাধান।
জোশুয়া শ্লাইচটিং

গত 4 বছর ধরে আমি কীভাবে জানতাম না যে এটি একটি জিনিস ছিল।
xorinzor

32

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

function someFunction() {
}

এবং নিম্নলিখিত অবজেক্ট,

var obj = { someFunction: someFunction };

আপনি যদি পদ্ধতি সিনট্যাক্স ব্যবহার করে যেমন ফাংশনটি কল করেন যেমন,

obj.someFunciton();

তারপর thisআবদ্ধ হয় obj

যদি আপনি সরাসরি কিছু ফাংশন () কল করেন যেমন,

someFunction();

তারপরে thisএটি বিশ্বব্যাপী অবজেক্টের সাথে আবদ্ধ window

চারপাশের সর্বাধিক সাধারণ কাজ হ'ল এটি বন্ধকরণের মধ্যে ধরা যেমন যেমন,

displayMe : function() {      

    // the 'this' pointer is referring to the std_obj      
    if (this.activeEffect=="fade") { }      
    var that = this;  
    var doSomeEffects = function() {      

      // the 'this' pointer is referring to global
      // that, however, refers to the outscope this
      if (that.activeEffect=="fade") { }      
    }      

    doSomeEffects();         
 }      

যে = এটি নিখুঁত
নেদার ওয়েবার

9

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

function myFirstObject(){
    var _this = this;
    this.name = "myFirstObject";
    this.getName = function(){
       console.log("_this.name = " + _this.name + " this.name = " + this.name);  
    }
}

function mySecondObject(){
    var _this = this;
    this.name = "mySecondObject";
    var firstObject = new myFirstObject();
    this.getName = firstObject.getName
}

var secondObject = new mySecondObject();
secondObject.getName();

আপনি এখানে চেষ্টা করে দেখতে পারেন: http://jsfiddle.net/kSTBy/

আপনার ফাংশনে যা ঘটছে তা হ'ল "doSomeEffects ()", তাকে স্পষ্টভাবে বলা হচ্ছে, এর অর্থ প্রসঙ্গ বা ফাংশনের "এটি" উইন্ডো। যদি "doSomeEffects" একটি প্রোটোটাইপ পদ্ধতি ছিল যেমন, "myObject" বলার জন্য এই.ডোসোমএফেক্টস, তবে মায়োবজেক্ট.ডোসোম এফেক্টস () "" এটি "" মাইবজেক্ট "হতে পারে।


4
অলস এবং অধৈর্য জন্য, এই ডেমো লগ করে:_this.name = myFirstObject this.name = mySecondObject
পিটিম

9

এই প্রশ্নটি বুঝতে, নিম্নলিখিত স্নিপেটের জন্য আউটপুট পাওয়ার চেষ্টা করুন

var myObject = {
    foo: "bar",
    func: function() {
        var self = this;
        console.log("outer func:  this.foo = " + this.foo);
        console.log("outer func:  self.foo = " + self.foo);
        (function() {
            console.log("inner func:  this.foo = " + this.foo);
            console.log("inner func:  self.foo = " + self.foo);
        }());
    }
};
myObject.func();

উপরের কোডটি নিম্নলিখিতটি কনসোলে আউটপুট দেবে:

outer func:  this.foo = bar
outer func:  self.foo = bar
inner func:  this.foo = undefined
inner func:  self.foo = bar

বাইরের ফাংশনে, এটি এবং স্ব উভয়ই মাইবজেক্টকে উল্লেখ করে এবং তাই উভয়ই যথাযথভাবে রেফারেন্স এবং অ্যাক্সেস করতে পারে oo

অভ্যন্তরীণ ফাংশনে, যদিও এটি আর মাইবজেক্টকে বোঝায় না। ফলস্বরূপ, এটি.ফু অভ্যন্তরীণ ফাংশনে অপরিজ্ঞাত, যেখানে স্থানীয় ভেরিয়েবলের স্ব উল্লেখটি স্কোপে রয়ে যায় এবং সেখানে অ্যাক্সেসযোগ্য। (ইসিএমএ ৫ এর পূর্বে, অভ্যন্তরীণ ফাংশনে এটি বৈশ্বিক উইন্ডো অবজেক্টকে বোঝায়; যদিও ইসিএমএ ৫ হিসাবে এটি অভ্যন্তরীণ ফাংশনটিতে অপরিবর্তিত থাকবে।)


4
অভ্যন্তরীণ ফাংশনে, thisউইন্ডো অবজেক্ট (ব্রাউজার পরিবেশে) বা গ্লোবাল অবজেক্ট (একটি
নোড.জেএস

4
কেন এমন হয়?
সেতু

@ ইরানশু "কঠোর ব্যবহার করুন" এবং thisউইন্ডোটির আর কোনও উল্লেখ করে না
রফ্রোল

3

কাইল দ্বারা ব্যাখ্যা করা হিসাবে, আপনি ব্যবহার করতে পারেন callবা ফাংশনটির মধ্যে applyনির্দিষ্ট করতে this:

আপনার কোডটিতে এই ধারণাটি প্রয়োগ করা হয়েছে:

var std_obj = {
    options: {
        rows: 0,
        cols: 0
    },
    activeEffect: "none",
    displayMe: function() {

        // the 'this' pointer is referring to the std_obj
        if (this.activeEffect == "fade") {}

        var doSomeEffects = function() {
            // the 'this' pointer is referring to the window obj, why?
            if (this.activeEffect == "fade") {}
        }

        doSomeEffects.apply(this,[]);
    }
};

std_obj.displayMe();

জেএসফিডাল


0

আমি একটি সতর্কতাও পেয়েছি "এর মাধ্যমে কোনও শ্রেণীর ক্ষেত্রে সম্ভাব্য অবৈধ রেফারেন্স অ্যাক্সেস "

class MyListItem {
    constructor(labelPrm) {
        this._flagActive = false;
        this._myLabel = labelPrm;
        labelPrm.addEventListener('click', ()=>{ this.onDropdownListsElementClick();}, false);
    }

    get myLabel() {
        return this._myLabel
    }
    get flagActive(){
        return this._flagActive;
    }

    onDropdownListsElementClick(){console.log("Now'this'refers to the MyListItem itself")}}//end of the class

0

যেহেতু এটি উল্লেখ করা হয়নি আমি উল্লেখ করব যে ব্যবহারটি .bind()একটি সমাধান -


        doSomeEffects=doSomeEffect.bind(this);
        doSomeEffects();   
      }
    };

    std_obj.displayMe();

এখানে আরও সহজ উদাহরণ -

bad = { 
  name:'NAME', 
  z : function() { 
    function x() { console.log(this.name); }; 
    x() 
  } 
};
bad.z() // prints 'undefined'

good = { 
  name:'NAME', 
  z : function() { 
    function x() { console.log(this.name); }; 
    x=x.bind(this);
    x();
  } 
};
good.z() // prints 'NAME'

এটি সত্য যে একটি তীর ফাংশনটি ব্যবহার করা =>চটকদার দেখায় এবং প্রোগ্রামারটির পক্ষে সহজ। যাইহোক, এটি মনে রাখা উচিত যে একটি লিক্সিকাল স্কোপটির প্রসেসিং এবং মেমরির ক্ষেত্রে সেই লেজিকাল স্কোপটি সেটআপ এবং বজায় রাখার জন্য আরও কাজ করা প্রয়োজন, কেবল কোনও ফাংশনটির thisসাথে পয়েন্টারের সাথে যুক্ত হওয়ার তুলনায় .bind()

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

এমডিএন থেকে

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

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