this詳細
4984 ワード
一、thisメカニズム thisは、作成時に結合された ではなく、実行時にバインディングされています. thisは、関数に依存した呼び出し方式を指す.
二、thisバインディング規則
1.標準バインディング
まず、最もよく使われている関数の呼び出し方法です.独立関数の呼び出しです.
2.陰式バインディング
(1)呼び出し位置にコンテキストオブジェクトがあるかどうか、またはあるオブジェクトに所有されているかどうか
(2)また、オブジェクト参照では、最後のレイヤーだけが呼び出し位置で機能します.
callでappy関数がthisの方向を変えます.
4.newバインディング
new呼び出し時に、関数が他のオブジェクトに戻らないと、newから出てきたオブジェクトに紐付けされます.
newバインディング>call/appy(明示的バインディング)>暗黙的バインディング>デフォルトのバインディングを証明します.
1.バインディングvs暗黙的バインディングを表示する
2.newバインディングvsバインディング
3.newバインディングvsはバインディングを表示します.
newバインディングはcall/applyと一緒に使えません.new foo.call(obj 1)という形でテストできません.私達はbindで試してみます. これまでにfooはObj 1に縛られていましたが、new bar(3)はbar(2)のように、Obj 1.aが変わっていません.Obj 1.aはまだ2です. はむしろbar.aが3になりました.new bar(3)の中(new bar)が一つの全体として有効であると説明しました. したがって、newバインディングは を示す.
四、バインディング例外
1.無視されたthis
null/undefinedをthisのバインディングオブジェクトとしてcall/apply/bindに入力すると、これらの値の呼び出しは無視され、デフォルトのバインディングルールに変わります.
五、矢印関数
矢印関数は、thisの4つの標準的な規則を使用しないで、外層作用領域に基づいてthisを決定します.
二、thisバインディング規則
1.標準バインディング
まず、最もよく使われている関数の呼び出し方法です.独立関数の呼び出しです.
function foo(){
console.log(this.a)
}
// a,
var a=2;
foo(); // 2
foo()呼び出しには何の修飾も参照しないので、デフォルトのバインディングのみを使用します.2.陰式バインディング
(1)呼び出し位置にコンテキストオブジェクトがあるかどうか、またはあるオブジェクトに所有されているかどうか
function foo(){
console.log(this.a)
}
var obj={
a:2,
foo:foo
}
obj.foo() // 2
関数fooはobjオブジェクトではありませんが、呼び出し位置はobjコンテキストを使用して関数を参照します.このとき、暗黙的なバインディングはこのコンテキストオブジェクトにthisバインディングされます.(2)また、オブジェクト参照では、最後のレイヤーだけが呼び出し位置で機能します.
function foo(){
console.log(this.a)
}
var obj2={
a:42,
foo:foo
}
var obj1={
a:2,
obj2:obj2
}
obj1.obj2.foo(); // 42
(3)暗黙的な紛失(デフォルトのバインディングに変わります)function foo(){
console.log(this.a)
}
var obj={
a:2,
foo:foo
}
var bar=obj.foo;
var a="oops, global";
bar(); // "oops, global"
barはobj.fooの引用ですが、実際にはfoo関数自体を参照してください.bar呼び出しには修飾がありません.したがって、デフォルトのバインディングです.function foo(){
console.log(this.a)
}
var obj={
a:2,
foo:foo
}
function doFoo(fn){
fn(); //
}
var a="oops, global";
doFoo(obj.foo); // "oops, global"
パラメータ伝達は、関数に過ぎず、前の栗と同じです.function foo(){
console.log(this.a)
}
var obj={
a:2,
foo:foo
}
var a="oops, global";
setTimeout(obj.foo,100); // "oops, global"
結果は同じです.違いはありません.setTimeoutはfunction setTimeout(fn,deplay){
// deplay
fn(); //
}
3.明示的なバインディング(ハードバインディング)callでappy関数がthisの方向を変えます.
function foo(){
console.log(this.a)
}
var obj={
a:2,
foo:foo
}
var bar=function(){
foo.call(obj);
}
bar(); // 2
setTimeout(bar,100); // 2
bar.call(window); // 2
ハードバインディングを見ても、thisの方向は変更できません.4.newバインディング
new呼び出し時に、関数が他のオブジェクトに戻らないと、newから出てきたオブジェクトに紐付けされます.
function foo(a){
this.a=a;
}
var bar=new foo(2);
console.log(bar.a); //2
var obj={
a:3
}
function boo(a){
this.a=a;
return obj; //
}
var baz=new boo(2);
console.log(baz.a); // 3
三、thisバインディング優先度newバインディング>call/appy(明示的バインディング)>暗黙的バインディング>デフォルトのバインディングを証明します.
1.バインディングvs暗黙的バインディングを表示する
function foo(){
console.log(this.a);
}
var obj1={
a:2,
foo:foo
}
var obj2={
a:3,
foo:foo
}
obj1.foo(); // 2
obj2.foo(); // 3
obj1.foo.call(obj2); // 3
obj2.foo.call(obj1); // 3
上記の証明:バインディングを表示する.2.newバインディングvsバインディング
function foo(something){
this.a=something;
}
var obj1={
foo:foo
}
var obj2={}
obj1.foo(2); //
console.log(obj1.a); // 2
obj1.foo.call(obj2,3); //
console.log(obj2.a); // 3
var bar=new obj1.foo(4);
console.log(obj1.a); // 2
console.log(bar.a); // 4
最後の3行のコードを見ると、newバインディング>暗黙的バインディング3.newバインディングvsはバインディングを表示します.
newバインディングはcall/applyと一緒に使えません.new foo.call(obj 1)という形でテストできません.私達はbindで試してみます.
function foo(something){
this.a=something;
}
var obj1={};
var bar=foo.bind(obj1);
bar(2);
console.log(obj1.a); // 2
var baz=new bar(3);
console.log(obj1.a); // 2
console.log(bar.a); // 3
最後の3行:四、バインディング例外
1.無視されたthis
null/undefinedをthisのバインディングオブジェクトとしてcall/apply/bindに入力すると、これらの値の呼び出しは無視され、デフォルトのバインディングルールに変わります.
function foo(){
console.log(this.a);
}
var a=2;
foo.call(null); // 2
//
function fo(a,b){
console.log("a:"+a+",b:"+b);
}
var bar = fo.bind(null,2);
bar(3); // a:2,b:3
2.間接参照function foo(){
console.log(this.a);
}
var a=2;
var o={a:3,foo:foo};
var p={a:4};
o.foo(); // 3
(p.foo=o.foo)(); // 2
p.foo=o.fooの戻り値は、ターゲット関数の参照であり、呼び出したfoo()は、p.foo()やo.foo()ではなく、標準バインディングです.五、矢印関数
矢印関数は、thisの4つの標準的な規則を使用しないで、外層作用領域に基づいてthisを決定します.
function foo(){
return (a)=>{
console.log(this.a);
}
}
var obj1={a:2};
var obj2={a:3};
var bar=foo.call(obj1);
bar.call(obj2); // 2 3
カッター関数がthisを結合した後、変更できません.function foo(){
setTimeout(()=>{
console.log(this.a);
},100)
}
var obj={a:2};
foo.call(obj); // 2
六、経典蔑視問題function Foo () {
getName = function () {
console.log(1);
};
return this;
}
Foo.getName = function () {
console.log(2);
};
Foo.prototype.getName = function () {
console.log(3);
};
var getName = function () {
console.log(4);
};
function getName () {
console.log(5);
}
Foo.getName(); // 2
getName(); // 4
Foo().getName(); // 1
getName(); // 1
new Foo.getName(); //2
new Foo().getName(); // 3
new new Foo().getName(); // 3