JSでのthis指向の変更
5352 ワード
JSでのthis指向の変更
JavaScriptでは、thisの指向性問題は前に要約されていますが、実際には、多くのシーンで
callはthis指向を変更します.
callの使用文法:func.call(thisArg,arg 1,arg 2,…)
call方法は、指定された
関数greetがコール()方法を呼び出してオブジェクトdogObjを渡すと、関数greet内部の
関数greetがcall()方法を呼び出して、対象pigObjを渡すと、関数greet内部の
call()が参加しない場合、厳格なモードで
匿名関数コール方法:
apply方法でthis指向を変更します.
applyの使用文法:func.apply(thisArg,[args Aray])
applyの使い方はcallの方法と似ていますが、callの方法はパラメータのリストにすぎません.上記の例では、callをappyに変更することができますが、apply方法は2つのパラメータしか受け入れられません.2番目のパラメータは1つの配列またはクラスの配列オブジェクトです.
bind方法でthis指向を変更します.
bindの使用文法:func.bind(thisArg,arg 1,arg 2,…)
bindのパラメータはcallと同じであるが、bindが返したのは、this指向を変更した関数の例である.
1秒後の遅延関数は、構造関数のdeclare方法を呼び出し、このとき、関数declare内の
ES 6の矢印関数は、thisの方向を変更します.
矢印関数の
Obj.f 2()実行後に印刷されるのは1です.f 2は矢印関数であり、関数の
もう一つの例を見ます.
まず焦らないでください.まずゆっくり分析してください.上の分析は正しいです.矢印関数の
矢印関数は、
JavaScriptでは、thisの指向性問題は前に要約されていますが、実際には、多くのシーンで
this
の指向性を変更する必要があります.this
方向の変更について議論します.callはthis指向を変更します.
callの使用文法:func.call(thisArg,arg 1,arg 2,…)
call方法は、指定された
this
値(thisが指すオブジェクト)と1つまたは複数のパラメータが必要である.this
値が提供されると、呼び出し関数内部のthis
のポインタが変更されます.// call this
var animal = ' ';
var times = '15 ';
function greet() {
let str = this.animal + ' :' + this.times;
console.log(str);
}
var dogObj = {
animal: ' ',
times: '8 '
};
var pigObj = {
animal: ' ',
times: '13 '
}
greet(); // :15
greet.call(dogObj); // :8
greet.call(pigObj); // :13
greet.call(); // :15
関数greetを直接呼び出すと、関数greet内部のthis
は、グローバルオブジェクトWindowを指す.関数greetがコール()方法を呼び出してオブジェクトdogObjを渡すと、関数greet内部の
this
はオブジェクトdogObjを指す.関数greetがcall()方法を呼び出して、対象pigObjを渡すと、関数greet内部の
this
はオブジェクトpigObjを指す.call()が参加しない場合、厳格なモードで
this
の値はundefinedとなります.そうでないと、グローバルオブジェクトWindowを指します.匿名関数コール方法:
var books = [{
name: 'CSS ',
price: 23
}, {
name: 'CSS ',
price: 35
}, {
name: 'JavaScript ',
price: 55
}];
for (var i = 0; i < books.length; i++) {
(function (i) {
// this call
this.printf = function () {
console.log(`${i} ${this.name}: ¥${this.price}`);
}
this.printf();
}).call(books[i], i);
}
// :
// 0 CSS : ¥23
// 1 CSS : ¥35
// 2 JavaScript : ¥55
callの継承が実現されました//
function CalcA(){
this.add = function(a, b){
return a + b;
}
}
//
function CalcS(){
this.sub = function(a, b){
return a - b;
}
}
//
function Calc(){
console.log(this); // Calc {}
CalcA.call(this);
CalcS.call(this);
console.log(this); // Calc {add: ƒ, sub: ƒ}
}
var calc = new Calc();
console.log(calc.add(2, 3)); // 5
console.log(calc.sub(10, 1));// 9
構造関数Calcは、カルル法により、構造関数CalcA、CalcSのthis
をCalc自身に向け、それらの属性および方法を継承した.したがって、構造関数Calcが生成した例示的なオブジェクトも、構造関数CalcA、CalcSにおける属性および方法にアクセスすることができる.apply方法でthis指向を変更します.
applyの使用文法:func.apply(thisArg,[args Aray])
applyの使い方はcallの方法と似ていますが、callの方法はパラメータのリストにすぎません.上記の例では、callをappyに変更することができますが、apply方法は2つのパラメータしか受け入れられません.2番目のパラメータは1つの配列またはクラスの配列オブジェクトです.
bind方法でthis指向を変更します.
bindの使用文法:func.bind(thisArg,arg 1,arg 2,…)
bindのパラメータはcallと同じであるが、bindが返したのは、this指向を変更した関数の例である.
var petalNum = 100;
function Flower() {
this.petalNum = Math.ceil(Math.random() * 10) + 1;
}
Flower.prototype.declare = function() {
console.log(this);
console.log('this is a beautiful flower with ' + this.petalNum + ' petals');
}
Flower.prototype.bloom = function() {
console.log(this); // Flower {petalNum: 7}
// this Window
window.setTimeout(this.declare, 1000);
// bind this, Flower
window.setTimeout(this.declare.bind(this), 2000);
}
var flower = new Flower();
flower.bloom();
インスタンスオブジェクトflowerがbloomメソッドを呼び出した後、bloom内のthis
は、構造関数のプロトタイプオブジェクトを指す.1秒後の遅延関数は、構造関数のdeclare方法を呼び出し、このとき、関数declare内の
this
はWindowを指す.印刷の結果は以下の通りです.// Window {parent: Window, postMessage: ƒ, blur: ƒ, focus: ƒ, close: ƒ, …}
// this is a beautiful flower with 100 petals
2秒後の遅延関数は構造関数のdeclare方法を呼び出し、このとき関数declareがbindを介してthis(構造関数のプロトタイプオブジェクト)をバインディングする.印刷の結果は以下の通りです.// , petalNum 。
// Flower {petalNum: 7}
// this is a beautiful flower with 7 petals
ここではbindをcallに変更します.applyは直ちに実行し、遅延効果は無効になります.ES 6の矢印関数は、thisの方向を変更します.
矢印関数の
this
は、関数を実行するときに結合するのではなく、関数を定義するときに結合される.定義時のバインディングとは、this
が、父から実行されたコンテキストを引き継ぐthis
である.var a = 1;
var obj = {
a: 2,
f1: function(){
console.log(this.a)
},
f2: () => {
console.log(this.a)
}
}
obj.f1(); // 2
obj.f2(); // 1
Obj.f 1()の実行後に印刷されるのは2であり、ここでは、Objがf 1関数を呼び出すと、関数のthis
は呼び出し対象のObjを指すことが分かります.ここでthis
は、関数を実行する際に結合されていることが分かる.Obj.f 2()実行後に印刷されるのは1です.f 2は矢印関数であり、関数の
this
は、父から実行されたコンテキストを引き継ぐthis
である.ここで矢印関数の親レベルはオブジェクトobjであり、Objの実行コンテキストはグローバルオブジェクトWindowであり、矢印関数のthis
はグローバルオブジェクトを指している.もう一つの例を見ます.
var a = 11;
function test() {
this.a = 22;
let b = () => { console.log(this.a) }
b();
}
test(); // 22
定義された理解では、11が印刷されるべきです.矢印関数親レベルの実行文脈はWindowグローバルオブジェクトですので、グローバルオブジェクトのaが印刷されます.まず焦らないでください.まずゆっくり分析してください.上の分析は正しいです.矢印関数の
this
はWindowオブジェクトを指しています.test関数がグローバル環境で呼び出されると、その内部のthis
はグローバルWindowオブジェクトを指し、コードのthis.a = 22;
はグローバル中のaを再割当するので、矢印関数がグローバルオブジェクトで見つかったa値は22である.コンソールにwindow.a
を入力して、グローバルオブジェクトのa値を確認し、結果プリント22を見ることができますので、矢印関数で印刷された結果がなぜ22なのかは分かりにくいです.コードのthis.a = 22;
をvar a = 22;
に変更すると、矢印関数で印刷された結果は11になる.矢印関数は、
this
のバインディング機構と同様に、外層関数で呼び出されたvar self = this;
を継承する.矢印関数では、this
は固定化を指し、矢印関数はもともと自分のthis
がないので、構造関数としては使えない.