ඇමතුමක් ලබා ගැනීමේදී නිවැරදි `මෙය` වෙත ප්‍රවේශ වන්නේ කෙසේද?


1449

මට සිදුවීම් හසුරුවන්නෙකු ලියාපදිංචි කරන ඉදිකිරීම් ශ්‍රිතයක් ඇත:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', function () {
        alert(this.data);
    });
}

// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};

// called as
var obj = new MyConstructor('foo', transport);

කෙසේ වෙතත්, මට dataඇමතුම තුළ නිර්මාණය කරන ලද වස්තුවේ දේපල වෙත ප්‍රවේශ විය නොහැක . පෙනෙන ආකාරයට එය thisනිර්මාණය කරන ලද වස්තුවට නොව වෙනත් එකකට යොමු වේ.

මම නිර්නාමික ශ්‍රිතයක් වෙනුවට වස්තු ක්‍රමයක් භාවිතා කිරීමට උත්සාහ කළෙමි:

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', this.alert);
}

MyConstructor.prototype.alert = function() {
    alert(this.name);
};

නමුත් එය එකම ගැටළු පෙන්නුම් කරයි.

නිවැරදි වස්තුවට ප්‍රවේශ විය හැක්කේ කෙසේද?


101
වරින් වර මම යම් ආකාරයක ප්‍රශ්නයක් සමඟ වෙහෙසට පත්ව සිටිමි, කැනොනිකල් පිළිතුරක් ලිවීමට මම තීරණය කරමි. මෙම ප්‍රශ්න වලට මිලියනය වතාවක් පිළිතුරු දී ඇතත්, සෑම විටම අදාළ නොවන තොරතුරු මගින් “දූෂිත” නොවන හොඳ ප්‍රශ්න + පිළිතුරු යුගලයක් සොයාගත නොහැක. මෙය එම අවස්ථාවන්ගෙන් එකක් වන අතර එම ප්‍රශ්න වලින් එකකි (මට කම්මැලියි). මෙම වර්ගයේ ප්‍රශ්න සඳහා ඇත්ත වශයෙන්ම හොඳ කැනොනිකල් ප්‍රශ්නයක් / පිළිතුරක් ඇතැයි ඔබ සිතන්නේ නම්, මට දන්වන්න, මම මෙය මකා දමමි. වැඩිදියුණු කිරීම් සඳහා යෝජනා සාදරයෙන් පිළිගනිමු!
ෆීලික්ස් ක්ලිං



Answers:


1818

ඔබ දැනගත යුතු දේ this

this(aka "සන්දර්භය") යනු එක් එක් ශ්‍රිතය තුළ ඇති විශේෂ මූල පදයක් වන අතර එහි වටිනාකම රඳා පවතින්නේ ශ්‍රිතය හැඳින්වූ ආකාරය මත මිස එය අර්ථ දැක්වූයේ කෙසේද / කවදාද යන්න මත නොවේ. වෙනත් විචල්‍යයන් මෙන් ශබ්දකෝෂ විෂය පථයන්ට එය බලපාන්නේ නැත (ඊතල ශ්‍රිත හැර, පහත බලන්න). මෙන්න උදාහරණ කිහිපයක්:

function foo() {
    console.log(this);
}

// normal function call
foo(); // `this` will refer to `window`

// as object method
var obj = {bar: foo};
obj.bar(); // `this` will refer to `obj`

// as constructor function
new foo(); // `this` will refer to an object that inherits from `foo.prototype`

පිළිබඳ වැඩිදුර දැන ගැනීමට this, MDN ප්‍රලේඛනය දෙස බලන්න .


නිවැරදි දේ වෙත යොමු වන්නේ කෙසේද this

භාවිතා නොකරන්න this

ඔබට ඇත්ත වශයෙන්ම ප්‍රවේශ වීමට අවශ්‍ය නැත this, නමුත් එය යොමු කරන වස්තුව . පහසු විසඳුමක් වන්නේ එම වස්තුවට යොමු වන නව විචල්‍යයක් නිර්මාණය කිරීමයි. විචල්යයට ඕනෑම නමක් තිබිය හැකි නමුත් පොදු ඒවා selfසහ that.

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function() {
        alert(self.data);
    });
}

සිට selfසාමාන්ය විචල්ය වේ, එය lexical පරාසය නීති පිළිපදින හා callback ඇතුළත ලබාගත හැකි ය. thisඇමතුම් ලබා ගැනීමේ වටිනාකම ඔබටම ලබා ගත හැකි වාසියද මෙයයි .

නැවත ඇමතුම පැහැදිලිව සකසා thisඇත - 1 කොටස

thisඑහි වටිනාකම ස්වයංක්‍රීයව සකසා ඇති නිසා ඔබට එහි වටිනාකම පාලනය කළ නොහැකි බව පෙනේ, නමුත් ඇත්ත වශයෙන්ම එය එසේ නොවේ.

සෑම ශ්‍රිතයකටම .bind [docs] ක්‍රමය ඇත , එය thisඅගයකට බැඳී නව ශ්‍රිතයක් ලබා දෙයි. මෙම ක්රියාව මඟින් ඔබට නම් එකක් ලෙස හරියටම එම චර්යාවක් .bindමත පමණක්, thisඔබ විසින් සකස් කරන ලදී. එම ශ්‍රිතය කෙසේ හෝ කවදා හැඳින්වුවද, thisසෑම විටම සම්මත අගය වෙත යොමු වේ.

function MyConstructor(data, transport) {
    this.data = data;
    var boundFunction = (function() { // parenthesis are not necessary
        alert(this.data);             // but might improve readability
    }).bind(this); // <- here we are calling `.bind()` 
    transport.on('data', boundFunction);
}

මෙම අවස්ථාවේ දී, අපි ඇමතුම් ආපසු thisලබා දෙන්නේ එහි වටිනාකමට MyConstructorthis.

සටහන: jQuery සඳහා සන්දර්භය බන්ධනය කිරීමේදී, ඒ වෙනුවට jQuery.proxy [docs] භාවිතා කරන්න. මෙය කිරීමට හේතුව, සිදුවීම් ඇමතුමක් ආපසු ලබා ගැනීමේදී ඔබට ශ්‍රිතය පිළිබඳ සඳහනක් ගබඩා කිරීමට අවශ්‍ය නොවන බැවිනි. jQuery එය අභ්‍යන්තරව හසුරුවයි.

ECMAScript 6: ඊතල ශ්‍රිත භාවිතා කරන්න

ECMAScript 6 ඊතල ශ්‍රිත හඳුන්වා දෙයි , එය ලැම්බඩා ශ්‍රිත ලෙස සිතිය හැකිය. ඔවුන්ට ඔවුන්ගේම thisබැඳීමක් නොමැත. ඒ වෙනුවට, thisසාමාන්‍ය විචල්‍යයක් මෙන් විෂය පථය දෙස බලයි. ඒ කියන්නේ ඔබට ඇමතිය යුතු නැත .bind. ඔවුන් සතුව ඇති එකම විශේෂ හැසිරීම එය නොවේ, කරුණාකර වැඩි විස්තර සඳහා MDN ප්‍රලේඛනය බලන්න.

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', () => alert(this.data));
}

thisඇමතුම් ලබා ගැනීමේ කට්ටලය - 2 කොටස

ඇමතුම් ආපසු භාරගන්නා සමහර කාර්යයන් / ක්‍රම මගින් ඇමතුම් ලබා ගත යුතු අගයක් ද පිළිගනී this. මෙය මූලිකවම එය ඔබම බැඳ තැබීම හා සමාන වේ, නමුත් ශ්‍රිතය / ක්‍රමය එය ඔබ වෙනුවෙන් කරයි. Array#map [docs] එවැනි ක්‍රමයකි. එහි අත්සන:

array.map(callback[, thisArg])

පළමු තර්කය ඇමතුම වන අතර දෙවන තර්කය වන්නේ අගය thisයොමු විය යුතුය. මෙන්න විවාදාත්මක උදාහරණයක්:

var arr = [1, 2, 3];
var obj = {multiplier: 42};

var new_arr = arr.map(function(v) {
    return v * this.multiplier;
}, obj); // <- here we are passing `obj` as second argument

සටහන: ඔබට වටිනාකමක් ලබා දිය හැකිද නැද්ද යන්න thisසාමාන්‍යයෙන් එම ශ්‍රිතයේ / ක්‍රමයේ ලේඛනවල සඳහන් වේ. උදාහරණයක් ලෙස, jQuery හි $.ajaxක්‍රමය [docs] පහත දැක්වෙන විකල්පය විස්තර කරයි context:

මෙම වස්තුව අජැක්ස් සම්බන්ධ සියලු ඇමතුම් වල සන්දර්භය බවට පත් කරනු ඇත.


පොදු ගැටළුව: වස්තු ක්‍රම ඇමතුම් / සිදුවීම් හසුරුවන්නන් ලෙස භාවිතා කිරීම

මෙම ගැටළුවේ තවත් පොදු ප්‍රකාශනයක් වන්නේ වස්තු ක්‍රමයක් ඇමතුම් / සිදුවීම් හසුරුවන්නා ලෙස භාවිතා කිරීමයි. කාර්යයන් ජාවාස්ක්‍රිප්ට් හි පළමු පන්තියේ පුරවැසියන් වන අතර “ක්‍රමය” යන පදය වස්තු දේපලක වටිනාකම වන ශ්‍රිතයක් සඳහා වූ වාචික යෙදුමකි. නමුත් එම ශ්‍රිතයට එහි “අඩංගු” වස්තුවට නිශ්චිත සම්බන්ධයක් නොමැත.

පහත උදාහරණය සලකා බලන්න:

function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = function() {
    console.log(this.data);
};

ශ්‍රිතය this.methodක්ලික් සිදුවීම් හසුරුවන්නා ලෙස පවරා ඇත, නමුත් document.bodyඑය ක්ලික් කළහොත් , ලොග් වූ අගය වනුයේ undefined, සිදුවීම් හසුරුවන්නා තුළ, thisයොමු දැක්වෙන්නේ document.bodyමිස උදාහරණය නොවේ Foo.
ආරම්භයේ දැනටමත් සඳහන් කර ඇති පරිදි, thisයොමු දක්වන්නේ ශ්‍රිතය හැඳින්වෙන ආකාරය මත මිස එය නිර්වචනය කර ඇති ආකාරය මත නොවේ .
කේතය පහත පරිදි වූවා නම්, ශ්‍රිතයට වස්තුවට ව්‍යංග යොමු කිරීමක් නොමැති බව වඩාත් පැහැදිලිව පෙනේ:

function method() {
    console.log(this.data);
}


function Foo() {
    this.data = 42,
    document.body.onclick = this.method;
}

Foo.prototype.method = method;

විසඳුම ඉහත සඳහන් කළ ආකාරයටම වේ: තිබේ නම්, නිශ්චිත අගයකට .bindපැහැදිලිවම බැඳීමට භාවිතා කරන්නthis

document.body.onclick = this.method.bind(this);

හෝ නිර්නාමික ශ්‍රිතයක් ඇමතුම් / සිදුවීම් හසුරුවන්නා ලෙස භාවිතා කිරීමෙන් වස්තුවෙහි “ක්‍රමයක්” ලෙස පැහැදිලිව අමතන්න සහ වස්තුව ( this) වෙනත් විචල්‍යයකට පවරන්න :

var self = this;
document.body.onclick = function() {
    self.method();
};

හෝ ඊතල ශ්‍රිතයක් භාවිතා කරන්න:

document.body.onclick = () => this.method();

41
ෆීලික්ස්, මම මීට පෙර මෙම පිළිතුර කියවා ඇති නමුත් කිසි විටෙකත් පිළිතුරු දුන්නේ නැත. මිනිසුන් භාවිතා කිරීම selfසහ thatයොමු කිරීම ගැන මම සැලකිලිමත් වෙමි this. මට මේ ආකාරයට දැනෙන්නේ thisවිවිධ සන්දර්භයන්හි අධික ලෙස පටවන ලද විචල්‍යයක් වන බැවිනි ; selfසාමාන්‍යයෙන් දේශීය උදාහරණයට අනුරූප වන අතර සාමාන්‍යයෙන් thatවෙනත් වස්තුවකට යොමු වේ. මම දන්නවා ඔබ මෙම රීතිය වෙනත් ස්ථාන ගණනාවක දර්ශනය වී ඇති බව මම දැක ඇති නමුත් එය භාවිතා කිරීමට පටන් ගෙන ඇත්තේ ඒ නිසාය _this, නමුත් ඒකාකාරී නොවන පුහුණුව හැරුණු විට අනෙක් අයට හැඟෙන්නේ කෙසේදැයි මට විශ්වාස නැත. එහි ප්‍රති .ලය වී ඇත.
vol7ron

3
Pro ෆීලික්ස්ක්ලිං මෙම ඇතුළත මූලාකෘති ශ්‍රිත භාවිතා කිරීමෙන් (සාමාන්‍යයෙන්) හැඳින්වෙන්නේ කෙසේ වෙතත් අපේක්ෂිත හැසිරීම සැමවිටම පවතිනු ඇතැයි උපකල්පනය කිරීම ආරක්ෂිතද? මූලාකෘති ශ්‍රිත තුළ ඇමතුම් ලබා ගැනීමේදී, බන්ධනය (), ස්වයං හෝ ඊට විකල්පයක් තිබේද?
andig

5
@FelixKling එය මත රඳා විටම ප්රයෝජනවත් විය හැකි Function.prototype.call ()හා Function.prototype.apply (). විශේෂයෙන් apply ()මම සැතපුම් ගණනක් ලබාගෙන ඇත. bind ()අනෙක් විකල්පයන්ට වඩා බන්ධනය භාවිතා කිරීමෙන් සුළු පොදු වාසි තිබිය හැකි බව මා දන්නා නමුත් (නමුත් නිශ්චිත නැත) සමහර විට පුරුද්දෙන් පමණක් භාවිතා කිරීමට මම නැඹුරු වෙමි .
නොලෝ

5
හොඳ පිළිතුරක් නමුත් අමතර විකල්ප විසඳුමක් එකතු කිරීම ගැන සලකා බලන්න, එය පන්ති, නව හෝ මෙය කිසිසේත් භාවිතා නොකිරීමට ය.
අළුආන් හඩාඩ්

4
ඊතල ශ්‍රිත "ඒ වෙනුවට, මෙය සාමාන්‍ය විචල්‍යයක් මෙන් විෂය පථයෙන් බලනු ලැබේ." මුළුමනින්ම මා වෙනුවෙන් මෙම ක්ලික් කිරීම සිදු කළා, ස්තූතියි! () => this.clicked();)
alphanumeric0101

214

ළමා සන්දර්භය තුළ මව් සන්දර්භයට ප්‍රවේශ විය හැකි ක්‍රම කිහිපයක් මෙන්න -

  1. ඔබට bind()ශ්‍රිතය භාවිතා කළ හැකිය .
  2. සන්දර්භය වෙත යොමු කිරීම / මෙය වෙනත් විචල්‍යයක් තුළ ගබඩා කරන්න (පහත උදාහරණය බලන්න).
  3. ES6 ඊතල ශ්‍රිත භාවිතා කරන්න .
  4. කේත / ක්‍රියාකාරී සැලසුම් / ගෘහ නිර්මාණ ශිල්පය වෙනස් කරන්න - මේ සඳහා ඔබට ජාවාස්ක්‍රිප්ට් හි සැලසුම් රටා පිළිබඳ විධානය තිබිය යුතුය .

1. bind()ශ්‍රිතය භාවිතා කරන්න

function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data', ( function () {
        alert(this.data);
    }).bind(this) );
}
// Mock transport object
var transport = {
    on: function(event, callback) {
        setTimeout(callback, 1000);
    }
};
// called as
var obj = new MyConstructor('foo', transport);

ඔබ භාවිතා කරන්නේ නම් underscore.js- http://underscorejs.org/#bind

transport.on('data', _.bind(function () {
    alert(this.data);
}, this));

සන්දර්භය / මෙය වෙනත් විචල්‍යයක් තුළ ගබඩා කිරීම

function MyConstructor(data, transport) {
  var self = this;
  this.data = data;
  transport.on('data', function() {
    alert(self.data);
  });
}

3 ඊතල ශ්‍රිතය

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

1
බන්ධනය () විකල්පය පුදුම සහගතය, එය මෙම වස්තුවේ දර්ශකය අනෙක් වස්තුව මතට ගමන් කිරීම පුදුම සහගතය (: ස්තූතියි!
ස්ටාව් බොඩික්

බන්ධනය () චාම් එකක් මෙන් ක්‍රියා කරයි. මගෙන් +1 ට බොහොම ස්තූතියි :)
අංජන සිල්වා

57

ඒ සියල්ලම "මැජික්" වාක්‍ය ඛණ්ඩයක් ලෙස හැඳින්වේ:

object.property();

ඔබ වස්තුවෙන් දේපල ලබාගෙන එය එකවර කැඳවූ විට, වස්තුව ක්‍රමවේදය සඳහා සන්දර්භය වනු ඇත. ඔබ එකම ක්‍රමයක් අමතන්නේ නම්, නමුත් වෙනම පියවර වලදී, සන්දර්භය ඒ වෙනුවට ගෝලීය විෂය පථය (කවුළුව) වේ:

var f = object.property;
f();

ඔබ ක්‍රමවේදයක් පිළිබඳ සඳහනක් ලබා ගත් විට, එය තවදුරටත් වස්තුවට සම්බන්ධ නොවේ, එය සරල ශ්‍රිතයක් සඳහා යොමු කිරීමක් පමණි. ඔබට ඇමතුමක් ලෙස භාවිතා කිරීම සඳහා යොමුව ලැබුණු විටත් එය සිදු වේ:

this.saveNextLevelData(this.setAll);

ඔබ ශ්‍රිතය සමඟ සන්දර්භය බැඳ තබන්නේ එතැනිනි:

this.saveNextLevelData(this.setAll.bind(this));

ඔබ jQuery භාවිතා කරන්නේ නම් $.proxy, ඒ වෙනුවට ඔබ සියලු ක්‍රම භාවිතා කළ යුතුය bind.

this.saveNextLevelData($.proxy(this.setAll, this));

34

"සන්දර්භය" සමඟ ඇති කරදර

"සන්දර්භය" යන පදය සමහර විට මෙය සඳහන් කරන වස්තුවට යොමු කරයි . එය එක්කෝ ශබ්දාර්ථයෙන් හෝ තාක්ෂණික ගැලපෙන නැති නිසා එය භාවිතා කිරීම නුසුදුසු සම්මතයන් ගේ මෙම .

“සන්දර්භය” යන්නෙන් අදහස් කරන්නේ යමක් එකතු කරන යමක් අවට ඇති තත්වයන් හෝ අමතර අර්ථයක් ලබා දෙන පෙර සහ පසු තොරතුරු ය. ක්‍රියාත්මක කිරීමේ සන්දර්භය වෙත යොමු කිරීම සඳහා "සන්දර්භය" යන පදය ECMAScript හි භාවිතා වේ , එය සියලු පරාමිතීන්, විෂය පථය සහ මෙය ක්‍රියාත්මක කිරීමේ කේතයක විෂය පථය තුළ වේ.

මෙය ECMA-262 වගන්තියේ 10.4.2 හි දක්වා ඇත :

ඇමතුම් ක්‍රියාත්මක කිරීමේ සන්දර්භයෙහි මෙම බන්ධනයට සමාන අගයකට මෙම බන්ධනය සකසන්න

එය පැහැදිලිවම පෙන්නුම් කරන්නේ මෙය ක්‍රියාත්මක කිරීමේ සන්දර්භයක කොටසක් බවයි.

ක්‍රියාත්මක කිරීමේ සන්දර්භය මඟින් ක්‍රියාත්මක වන කේතයට අර්ථයක් එක් කරන අවට තොරතුරු සපයයි. මෙම බන්ධනයට වඩා බොහෝ තොරතුරු එයට ඇතුළත් ය .

ඒ නිසා වටිනාකම මෙම "සන්දර්භය" නොවේ, එය ක්රියාත්මක කිරීම සන්දර්භය එක් කොටසක් පමණකි වේ. එය අත්‍යවශ්‍යයෙන්ම දේශීය විචල්‍යයක් වන අතර එය ඕනෑම වස්තුවකට ඇමතුමකින් සහ දැඩි ආකාරයකින් ඕනෑම අගයකට සැකසිය හැකිය.


මෙම පිළිතුර සමඟ එකඟ විය නොහැක. “ක්‍රියාත්මක කිරීමේ සන්දර්භය” යන යෙදුමේ පැවැත්ම “ක්‍රියාත්මක කිරීමේ” වෙනත් භාවිතයන් තහනම් කරනවාට වඩා “සන්දර්භය” හි වෙනත් භාවිතයන් තහනම් නොකරයි. විස්තර කිරීමට වඩා හොඳ යෙදුමක් තිබිය හැකි thisනමුත් මෙහි කිසිවක් ඉදිරිපත් නොකෙරෙන අතර "සන්දර්භය" මත දොර වැසීමට ප්‍රමාද වැඩියි.
රෝමර් -1888

@ රෝමර් -1888 the සංස්කරණයට ස්තූතියි. ඔබ හරි, නමුත් මගේ තර්කය වෙනත් අරමුණු සඳහා “සන්දර්භය” වළක්වා “ක්‍රියාත්මක කිරීමේ සන්දර්භය” පැවතීම මත රඳා නොපවතී. ඒ වෙනුවට, එය පදනම් වී ඇත්තේ තාක්‍ෂණික හා අර්ථකථන දෘෂ්ටි කෝණයෙන් නුසුදුසු “සන්දර්භය” මත ය. "මෙය" වෙනුවට "සන්දර්භය" භාවිතය අහෝසි වෙමින් පවතින බව මම සිතමි. මෙම හෝ මෙම බන්ධනයට විකල්ප යෙදුමක් සොයා ගැනීමට මට කිසිදු හේතුවක් නොපෙනේ , එය හුදෙක් අපැහැදිලි වන අතර යම් අවස්ථාවක දී “සන්දර්භය” ඇත්ත වශයෙන්ම මෙය බවත් එය කෙසේ හෝ “සන්දර්භය” තුළ නොමැති බවත් පැහැදිලි කළ යුතුය. :-)
RobG

මෙය කිසිසේත් “සන්දර්භය” නොවන බව ඔබට කිව හැකි යැයි මම නොසිතමි, එය ක්‍රියාත්මක කිරීමේ සන්දර්භයේ එක් කොටසක් බව ඔබ දැනටමත් පිළිගෙන ඇති විට, “ක්‍රියාත්මක කිරීම” යනු හුදෙක් නාමමාත්‍රයකි.
රෝමර් -1888

@ රෝමර් -1888 this මම මේ සංවාදය දිගටම කරගෙන යන්නේ නැහැ. ඔව්, මේ වන කොටස කියාත්මක සන්දර්භයෙන්. ඒක කියා එම සන්දර්භය කණ්ඩායමක් එක් ක්රීඩකයා කණ්ඩායම කියනවා වගේ.
RobG

රොබ්, අනුකම්පාව ඔබට ඉදිරියට යාමට අවශ්‍ය නැත. එය සිත්ගන්නා විවාදයකි. මට ඔබේ කාලය ලබා දීම ගැන ස්තූතියි.
රෝමර් -1888

32

"මෙම" මූල පදය ගැන ඔබ දැනගත යුතුය.

මගේ මතය අනුව ඔබට "මෙය" ආකාර තුනකින් ක්‍රියාත්මක කළ හැකිය (ස්වයං / ඊතල ක්‍රියාකාරිත්වය / බන්ධන ක්‍රමය)

ශ්‍රිතයක මෙම මූල පදය වෙනත් භාෂාවන්ට සාපේක්ෂව ජාවාස්ක්‍රිප්ට් හි ටිකක් වෙනස් ලෙස ක්‍රියා කරයි.

එය දැඩි මාදිලිය සහ දැඩි නොවන මාදිලිය අතර යම් වෙනස්කම් ද ඇත.

බොහෝ අවස්ථාවන්හීදී, මෙහි වටිනාකම තීරණය වන්නේ ශ්‍රිතයක් හැඳින්වෙන ආකාරය අනුව ය.

ක්‍රියාත්මක කිරීමේදී පැවරුම මඟින් එය සැකසිය නොහැකි අතර, ශ්‍රිතය හැඳින්වෙන සෑම අවස්ථාවකම එය වෙනස් විය හැකිය.

ශ්‍රිතයක වටිනාකම කෙසේ වෙතත් එය නියම කිරීම සඳහා ES5 බන්ධන () ක්‍රමය හඳුන්වා දුන්නේය.

සහ ES2015 විසින් ඊතල ශ්‍රිත හඳුන්වා දී ඇති අතර එමඟින් මෙම බන්ධනය ලබා නොදේ (එය සංක්ෂිප්ත ශබ්දකෝෂ සන්දර්භයේ මෙම අගය රඳවා ගනී).

ක්රමය 1: සන්දර්භය වෙනස් වන විට පවා මුල් පිටපත පිළිබඳ සඳහනක් පවත්වා ගැනීම සඳහා ස්වයං - ස්වයං භාවිතා වේ. එය බොහෝ විට සිදුවීම් හසුරුවන්නන් (විශේෂයෙන් වසා දැමීම් වලදී) භාවිතා කරන තාක්‍ෂණයකි.

යොමුව : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this

function MyConstructor(data, transport) {
    this.data = data;
    var self = this;
    transport.on('data', function () {
        alert(self.data);
    });
}

ක්‍රමය 2 : ඊතල ශ්‍රිතය - ඊතල ශ්‍රිත ප්‍රකාශනය යනු නිත්‍ය ශ්‍රිත ප්‍රකාශනයකට කෘතිමව සංයුක්ත විකල්පයකි,

මේ සඳහා තමන්ගේම බැඳීම් නොමැතිව වුවද, තර්ක, සුපිරි හෝ නව ඉලක්ක ඉලක්ක.

ඊතල ශ්‍රිත ප්‍රකාශන ක්‍රම ලෙස නොගැලපෙන අතර ඒවා ඉදිකිරීම්කරුවන් ලෙස භාවිතා කළ නොහැක.

යොමුව : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',()=> {
        alert(this.data);
    });
}

ක්‍රමය 3 : බන්ධනය- බන්ධන () ක්‍රමය මඟින් නව ශ්‍රිතයක් නිර්මාණය කරයි,

අමතන විට, එහි මූල පදය සපයා ඇති අගයට සකසා තිබේද,

නව ශ්‍රිතය හැඳින්වූ විට ලබා දී ඇති ඕනෑම තර්කයකට පෙර දී ඇති තර්ක මාලාවක් සමඟ.

යොමුව: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_objects/Function/bind

  function MyConstructor(data, transport) {
    this.data = data;
    transport.on('data',(function() {
        alert(this.data);
    }).bind(this);

26

පළමුව, සන්දර්භය තුළ ඔබට මූලික වචන පිළිබඳ පැහැදිලි අවබෝධයක් scopeසහ හැසිරීමක් thisතිබිය scopeයුතුය.

this& scope:


there are two types of scope in javascript. They are :

   1) Global Scope

   2) Function Scope

කෙටියෙන් කිවහොත්, ගෝලීය විෂය පථය යනු කවුළු වස්තුවට ය. ගෝලීය විෂය පථයකින් ප්‍රකාශිත විචල්‍යතාවන් ඕනෑම තැනකින් ලබා ගත හැකිය. අනෙක් අතට ශ්‍රිත විෂය පථය ශ්‍රිතයක් තුළ වාසය කරයි. ශ්‍රිතයක් තුළ ප්‍රකාශයට පත් කළ හැකි විචල්‍යතාව සාමාන්‍යයෙන් බාහිර ලෝකයෙන් ප්‍රවේශ විය නොහැක. thisගෝලීය විෂය පථයේ මූල පදය කවුළු වස්තුවට යොමු වේ. thisඇතුළත ශ්‍රිතය කවුළු වස්තුවට ද යොමු වේ. එබැවින් අපගේ තේරීමෙහි සන්දර්භයක් thisදැක්වීමට හැසිරවීමට ක්‍රමයක් සොයා ගන්නා තෙක් සෑම විටම කවුළුව වෙත යොමු වේ this.

--------------------------------------------------------------------------------
-                                                                              -
-   Global Scope                                                               -
-   ( globally "this" refers to window object)                                 -     
-                                                                              -
-         function outer_function(callback){                                   -
-                                                                              -
-               // outer function scope                                        -
-               // inside outer function"this" keyword refers to window object -                                                                              -
-              callback() // "this" inside callback also refers window object  -

-         }                                                                    -
-                                                                              -
-         function callback_function(){                                        -
-                                                                              -
-                //  function to be passed as callback                         -
-                                                                              -
-                // here "THIS" refers to window object also                   -
-                                                                              -
-         }                                                                    -
-                                                                              -
-         outer_function(callback_function)                                    -
-         // invoke with callback                                              -
--------------------------------------------------------------------------------

thisඇමතුම් ආපසු ගැනීමේ කාර්යයන් හැසිරවීමට විවිධ ක්‍රම :

මෙන්න මට පුද්ගල නමින් ඉදිකිරීම් ශ්‍රිතයක් ඇත. එයට දේපළක් යනුවෙන් හැඳින්වෙන nameක්‍රමයක් ඇත sayNameVersion1, sayNameVersion2සහ sayNameVersion3,, sayNameVersion4. ඔවුන් හතර දෙනාටම එක් නිශ්චිත කාර්යයක් ඇත. ඇමතුමක් ලබාගෙන එය ඉල්ලා සිටින්න. ඇමතුම් ලබා ගැනීම සඳහා නිශ්චිත කාර්යයක් ඇත.

function Person(name){

    this.name = name

    this.sayNameVersion1 = function(callback){
        callback.bind(this)()
    }
    this.sayNameVersion2 = function(callback){
        callback()
    }

    this.sayNameVersion3 = function(callback){
        callback.call(this)
    }

    this.sayNameVersion4 = function(callback){
        callback.apply(this)
    }

}

function niceCallback(){

    // function to be used as callback

    var parentObject = this

    console.log(parentObject)

}

දැන් අපි පුද්ගලයා ඉදිකිරීමටත් හා විවිධ සංස්කරණ පහ නිදසුනක් නිර්මාණය කරමු sayNameVersionX(X 1,2,3,4 අදහස්) සමග ක්රමය niceCallbackඅපි භාවිතා කළ හැකිය ආකාරය බොහෝ ක්රම බලන්න thisවලට යොමු වීමට ඇතුළත callback personඋදාහරණයක්.

var p1 = new Person('zami') // create an instance of Person constructor

බන්ධනය:

කළ යුතු දෙය නම් thisසපයා ඇති අගයට යතුරුපදය සකසා නව ශ්‍රිතයක් නිර්මාණය කිරීමයි .

sayNameVersion1හා sayNameVersion2භාවිතය හැසිරවීමට බැඳ thisඇති callback කාර්යය.

this.sayNameVersion1 = function(callback){
    callback.bind(this)()
}
this.sayNameVersion2 = function(callback){
    callback()
}

පළමුවැන්න thisක්‍රමවේදය තුළම ඇමතුම් ලබා ගැනීම සමඟ බැඳී ඇත. දෙවැන්න සඳහා ඇමතුමක් ලබා දෙන්නේ එයට බැඳී ඇති වස්තුව සමඟ ය.

p1.sayNameVersion1(niceCallback) // pass simply the callback and bind happens inside the sayNameVersion1 method

p1.sayNameVersion2(niceCallback.bind(p1)) // uses bind before passing callback

අමතන්න:

මෙම first argumentපිළිබඳ callක්රමයක් ලෙස භාවිතා කරයි thisසමඟ පළ කළහ කරන කාර්යය තුළ callඑය අමුණා ඇත.

sayNameVersion3කවුළු වස්තුව වෙනුවට අප විසින් නිර්මාණය කරන ලද පුද්ගල වස්තුව වෙත යොමු callකිරීම හැසිරවීමට භාවිතා කරයි this.

this.sayNameVersion3 = function(callback){
    callback.call(this)
}

එය පහත පරිදි වේ.

p1.sayNameVersion3(niceCallback)

අයදුම් කරන්න:

සමාන call, පළමු තර්කය applyයන්නෙන් අදහස් කෙරෙනුයේ thisමූල පදයෙන් දැක්වේ.

sayNameVersion4පුද්ගල වස්තුව වෙත යොමු කිරීම applyසඳහා හැසිරවීමට භාවිතා කරයිthis

this.sayNameVersion4 = function(callback){
    callback.apply(this)
}

එය පහත සඳහන් ආකාරයට හැඳින්වේ. ඇමතුම ලබා දීම සරලවම,

p1.sayNameVersion4(niceCallback)

1
පිළිතුර සම්බන්ධයෙන් ඕනෑම නිර්මාණාත්මක විවේචනයක් අගය කරනු ඇත!
AL-zami

1
ගෝලීය විෂය පථයේ ඇති මෙම මූල පදය අනිවාර්යයෙන්ම කවුළු වස්තුවට යොමු නොවේ . එය සත්‍ය වන්නේ බ්‍රව්සරයක පමණි.
රැන්ඩල් ධජය

1
AndRandallFlagg මම මෙම පිළිතුර ලිව්වේ බ්‍රව්සරයේ දෘෂ්ටිකෝණයෙනි. අවශ්‍ය නම් මෙම පිළිතුර වැඩි දියුණු කිරීමට නිදහස් වන්න :)
AL-zami

19

ගෝලීය වස්තුව (කවුළුව)setTimeout() සමඟ එය සැමවිටම ක්‍රියාත්මක වන බැවින් අපට මෙය බැඳ තැබිය නොහැක , ඔබට ඇමතුම් ආපසු ගැනීමේ ශ්‍රිතයේ සන්දර්භයට ප්‍රවේශ වීමට අවශ්‍ය නම්, අපට ලබා ගත හැකි ඇමතුම් ආපසු ගැනීමේ ශ්‍රිතය භාවිතා කිරීමෙන් :thisbind()

setTimeout(function(){
    this.methodName();
}.bind(this), 2000);

9
දැනට පවතින ඕනෑම පිළිතුරකට වඩා මෙය වෙනස් වන්නේ කෙසේද?
ෆීලික්ස් ක්ලිං

14

ප්‍රශ්නය thisජාවාස්ක්‍රිප්ට් හි ප්‍රධාන වචන හැසිරෙන ආකාරය වටා ය . thisපහත පරිදි වෙනස් ලෙස හැසිරේ,

  1. අගය thisසාමාන්‍යයෙන් තීරණය වන්නේ ශ්‍රිත ක්‍රියාත්මක කිරීමේ සන්දර්භයෙනි.
  2. ගෝලීය විෂය පථය තුළ, thisගෝලීය වස්තුව ( windowවස්තුව) යන්නෙන් අදහස් කෙරේ .
  3. කිසියම් ශ්‍රිතයක් සඳහා දැඩි මාදිලිය සක්‍රීය කර ඇත්නම්, එහි අගය දැඩි ප්‍රකාරයට සමාන thisවනු ඇත undefined, ගෝලීය වස්තුව යොමු වන්නේ වස්තුව undefinedවෙනුවට ය window.
  4. තිත ඉදිරිපිට සිටගෙන සිටින වස්තුව මෙම මූල පදය බැඳී ඇත්තේ කුමක් ද යන්නයි.
  5. අප සමඟ සුවිශේෂව මෙම අගය සැකසිය හැක call(), bind(), සහapply()
  6. වූ විට newමූල පදය භාවිතා (අ ඉදිකිරීමටත්), මෙම නව වස්තුව නිර්මාණය කෙරෙමින් කිරීමට බැඳී ඇත.
  7. ඊතල කාර්යයන් බැඳී නැත this - ඒ වෙනුවට, thisශබ්දකෝෂයෙන් බැඳී ඇත (එනම් මුල් සන්දර්භය මත පදනම්ව)

බොහෝ පිළිතුරු යෝජනා කරන පරිදි, අපට ඊතල ශ්‍රිතය හෝ bind()ක්‍රමය හෝ ස්වයං var භාවිතා කළ හැකිය . ගූගල් ජාවාස්ක්‍රිප්ට් ස්ටයිල් ගයිඩ් වෙතින් ලැම්බඩාස් (ඊතල ක්‍රියාකාරිත්වය) පිළිබඳ කරුණක් මම උපුටා දක්වන්නෙමි

ඊ.බී. (මෙය) සහ විශේෂයෙන් goog.bind (f, මෙය) හරහා ඊතල ශ්‍රිත භාවිතා කිරීමට කැමති වන්න. Const self = මෙය ලිවීමෙන් වළකින්න. ඊතල ශ්‍රිත ඇමතුම් සඳහා විශේෂයෙන් ප්‍රයෝජනවත් වන අතර සමහර විට අනපේක්ෂිත අතිරේක තර්ක ඉදිරිපත් කරයි.

ගූගල් පැහැදිලිවම නිර්දේශ කරන්නේ බැඳීමට වඩා ලැම්බඩා භාවිතා කිරීමට හෝ const self = this

එබැවින් හොඳම විසඳුම වනුයේ පහත පරිදි ලැම්බඩාස් භාවිතා කිරීමයි,

function MyConstructor(data, transport) {
  this.data = data;
  transport.on('data', () => {
    alert(this.data);
  });
}

යොමුව:

  1. https://medium.com/tech-tajawal/javascript-this-4-rules-7354abdb274c
  2. arrow-functions-vs-bind

මෙම ප්‍රශ්නය විශේෂයෙන් කාර්යයන් / ක්‍රම ඇමතුම් ලෙස භාවිතා කිරීම පිළිබඳව වේ. ඔබගේ පිළිතුර stackoverflow.com/q/3127429/218196 සඳහා වඩා හොඳ සුදුසුකමක් විය හැකිය .
ෆීලික්ස් ක්ලින්ග්

El ෆීලික්ස්ක්ලිං ඔව් ප්‍රශ්නය වන්නේ එම ප්‍රධාන ප්‍රශ්නයේ දී ඇමතුම් ලෙස ක්‍රියා / ක්‍රම භාවිතා කිරීම ය. thisප්‍රධාන වචන හැසිරවීම නිසා මගේ පිළිතුර කොටස් දෙකකට බෙදා ඇත this. පිළිතුර සංස්කරණය කිරීමට නිදහස් වන්න.
Code_Mode

ඔබේ සිව්වන කරුණ නොපැහැදිලි ලෙස මට පෙනේ. “මෙම වස්තුව කෝල්බැක් ලෙස ක්‍රම භාවිතා කිරීමේදී ඇති ගැටළුව” උදාහරණය සලකා බලන්න , එහිදී නිවැරදි වස්තුව තිත ඉදිරිපිට සිටගෙන සිටියද සන්දර්භය එම වස්තුව නොවේ.
bleistift2

8

කේත තුළ පන්ති භාවිතා කරන්නේ නම් දැනට වෙනත් ප්‍රවේශයක් ඇත.

පන්ති ක්ෂේත්‍රවල සහාය ඇතිව එය ඊළඟ මාර්ගයට ගෙන යා හැකිය:

class someView {
    onSomeInputKeyUp = (event) => {
        console.log(this); // this refers to correct value
    // ....
    someInitMethod() {
        //...
        someInput.addEventListener('input', this.onSomeInputKeyUp)

නිසැකවම කබාය යටතේ සන්දර්භය බන්ධනය කරන පැරණි හොඳ ඊතල ශ්‍රිතයක් වන නමුත් මෙම ස්වරූපයෙන් එය පැහැදිලි බන්ධනය වඩා පැහැදිලිව පෙනේ.

එය 3 වන අදියර යෝජනාව බැවින් දැනට (08/2018) එය සැකසීමට ඔබට බාබල් සහ සුදුසු බේබල් ප්ලගිනයක් අවශ්‍ය වේ.


2
ටයිප්ස්ක්‍රිප්ට් හි වැඩ කිරීමට මට ලැබුණේ මෙයයි: public methodName = (params) => { body }පන්තියක් තුළ.
yeyeyerman

5

සිදුවීම් සවන්දෙන්නන් තුළ බැඳීමට DOM2 සිට සම්මත ක්‍රමය වන තවත් ප්‍රවේශයක් නම්, ඔබට සැමවිටම සවන්දෙන්නන් ඉවත් කිරීමට ඉඩ සලසයි (වෙනත් ප්‍රතිලාභ අතර), අතුරු මුහුණතේ ක්‍රමය :thishandleEvent(evt)EventListener

var obj = {
  handleEvent(e) {
    // always true
    console.log(this === obj);
  }
};

document.body.addEventListener('click', obj);

භාවිතා කිරීම පිළිබඳ සවිස්තර තොරතුරු handleEventමෙතැනින් ලබා ගත හැකිය: https://medium.com/@WebReflection/dom-handleevent-a-cross-platform-standard-since-year-2000-5bf17287fd38


0

this JS හි:

thisJS හි අගය 100% තීරණය වන්නේ ශ්‍රිතයක් හැඳින්වෙන ආකාරය මත මිස එය අර්ථ දක්වන ආකාරය අනුව නොවේ. 'තිත් රීතියේ වම්පස'this මඟින් අපට සාපේක්ෂව පහසුවෙන් සොයාගත හැකිය :

  1. ශ්‍රිත මූල පදය භාවිතයෙන් ශ්‍රිතය නිර්මාණය කරන විට එහි අගය ලෙස thisහැඳින්වෙන්නේ ශ්‍රිතයේ තිතෙහි ඉතිරි වස්තුවයි
  2. තිතෙහි වස්තුවක් ඉතිරිව නොමැති නම්, thisශ්‍රිතයක් තුළ ඇති අගය බොහෝ විට ගෝලීය වස්තුව වේ ( globalනෝඩයේ, windowබ්‍රව්සරයේ). thisමෙහි මූල පදය භාවිතා කිරීම මම නිර්දේශ නොකරමි, මන්ද එය වැනි දෙයක් භාවිතා කිරීමට වඩා පැහැදිලි නොවන බැවිනි window!
  3. ඊතල ශ්‍රිත සහ ශ්‍රිතය භාවිතා කර නිර්මාණය කරන ලද Function.prototype.bind()ශ්‍රිත වැනි නිශ්චිත ව්‍යුහයන් එහි අගය නිවැරදි කළ හැකිය this. මේවා නීතියේ ව්‍යතිරේකයන් වන නමුත් එහි වටිනාකම නිවැරදි කිරීමට සැබවින්ම උපකාරී වේ this.

NodeJS හි උදාහරණය

module.exports.data = 'module data';
// This outside a function in node refers to module.exports object
console.log(this);

const obj1 = {
    data: "obj1 data",
    met1: function () {
        console.log(this.data);
    },
    met2: () => {
        console.log(this.data);
    },
};

const obj2 = {
    data: "obj2 data",
    test1: function () {
        console.log(this.data);
    },
    test2: function () {
        console.log(this.data);
    }.bind(obj1),
    test3: obj1.met1,
    test4: obj1.met2,
};

obj2.test1();
obj2.test2();
obj2.test3();
obj2.test4();
obj1.met1.call(obj2);

ප්‍රතිදානය:

රූප විස්තරය මෙහි ඇතුළත් කරන්න

1 සිට 1 දක්වා ප්‍රතිදානයන් හරහා ඔබට ගමන් කිරීමට මට ඉඩ දෙන්න (පළමු ලොගය දෙවන සිට ආරම්භ කිරීම නොසලකා හැරීම):

  1. thisඇත obj2නිසා තිතක් පාලනය වමේ අපි ආකාරය අපට දැකගත හැකිය test1ලෙස හැඳින්වේ obj2.test1();. obj2තිතෙන් ඉතිරි වන අතර එමඟින් thisඅගය.
  2. තිතෙන් obj2ඉතිරි වුවද , ක්‍රමවේදය හරහා test2බැඳී ඇත . එබැවින් වටිනාකම වේ .obj1bind()thisobj1
  3. obj2ශ්‍රිතයෙන් තිතෙන් වම් පසින් හැඳින්වේ : obj2.test3(). එබැවින් obj2එහි වටිනාකම වනු ඇත this.
  4. මෙම අවස්ථාවේ දී: obj2.test4() obj2තිතෙහි ඉතිරි වේ. කෙසේ වෙතත් ඊතල ක්‍රියාකාරිත්වයට තමන්ගේම thisබන්ධනයක් නොමැත. එබැවින් එය ආරම්භයේ දී ලොග් thisවූ module.exportsවස්තුව වන බාහිර විෂය පථයේ වටිනාකමට බැඳී ඇත .
  5. ශ්‍රිතය thisභාවිතා කිරීමෙන් අපට එහි අගය ද නියම කළ හැකිය call. මෙහිදී අපට අපේක්ෂිත thisඅගය තර්කයක් ලෙස සම්මත කළ හැකිය , එය obj2මේ අවස්ථාවේ දී ය.
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.