関数呼び出しの4パターンを深く理解する
3263 ワード
前の話
関数はいずれのプログラミング言語としてもコアです.jsに精通したいなら、この面でもっと工夫する必要があります.JavaScriptの関数は対象となります.この文章は多くのブログを見てからまとめたものです.
関数呼び出しの4つのモード
●一般関数としての呼び出し●オブジェクトとしてのメソッド呼び出し●コンストラクター呼び出し●callとappyメソッドの間接呼び出し
一般関数として呼び出す
通常の関数の呼び出しは、グローバルオブジェクトwindowに結合されますので、グローバル変数は書き換えられます.
関数がオブジェクトの属性として使用される場合、この関数はオブジェクトと呼ばれる方法です.方法が起動されると、thisはオブジェクトに結合されます.
関数またはメソッドが呼び出される前にnewキーワードがあれば、それは構造関数の呼び出しです.
関数の本生も対象です.各関数にはcall()とappy()の方法があります.それらを使って、関数を間接的に呼び出すことができます.call()とappy()は、this指向を変えることができます.二つの方法の役割は同じですが、パラメータリストが異なるだけです.call()とappy()は、チルのもう一つの文章「call()とappy()を深く理解する」を見ることができます.
関数はいずれのプログラミング言語としてもコアです.jsに精通したいなら、この面でもっと工夫する必要があります.JavaScriptの関数は対象となります.この文章は多くのブログを見てからまとめたものです.
関数呼び出しの4つのモード
●一般関数としての呼び出し●オブジェクトとしてのメソッド呼び出し●コンストラクター呼び出し●callとappyメソッドの間接呼び出し
一般関数として呼び出す
function add(x, y) {
return x + y;
}
var sum = add(1, 2);//
console.log(sum);
通常の関数での呼び出しは、非厳密モードでは、thisをグローバルオブジェクトに結合し、厳密モードでは、thisはundefinedです. function add(x, y) {
console.log(this);//window
}
add();
function add(x, y) {
'use strict';
console.log(this);// undefined
}
書き換える通常の関数の呼び出しは、グローバルオブジェクトwindowに結合されますので、グローバル変数は書き換えられます.
var a = 0;
function fn() {
this.a = 2;
}
fn();
console.log(this, this.a, a);// window 2 2
オブジェクトとしてのメソッド呼び出し関数がオブジェクトの属性として使用される場合、この関数はオブジェクトと呼ばれる方法です.方法が起動されると、thisはオブジェクトに結合されます.
var obj = {
fn: function() {
console.log(this);// {fn:f}
};
obj.fn();// , this obj
オブジェクトとしてのメソッド呼び出しは、オブジェクトの属性値を取得または変更することができます. var obj = {
a : 1,
m: function() {
return this;
},
n: function() {
this.a = 2;
}
}
console.log(obj.m().a);// 1
obj.n();
console.log(obj.m().a);// 2
注意:変数と違って、thisはスコープの制限がないので、ネスト関数は呼び出された関数からthisを引き継ぎません.ネスト関数がオブジェクトとなる方法で呼び出された場合、そのthisはこの方法を呼び出すオブジェクトを指します.ネスト関数が普通の関数として呼び出されると、厳密でないモードではWindowsを指し、厳密なモードではundefinedです. var obj = {
m: function() {
function n () {
return this;
}
return n();//
}
}
console.log(obj.m());// window
外層にアクセスしたいなら、thisを保存できます. var obj = {
m: function() {
var that = this;
function n() {
return that;
}
return n();
}
}
console.log(obj.m() === obj);// true
コンストラクタモード関数またはメソッドが呼び出される前にnewキーワードがあれば、それは構造関数の呼び出しです.
function fn() {
this.a = 1;
}
var obj = new fn();
console.log(obj.a);//1
/*
コンストラクタは通常returnキーを持っていません.この場合コンストラクタコールは新しいオブジェクトを返します.コンストラクタのthisはこのオブジェクトを指します. function fn() {
this.a = 2;
}
var test = new fn();
console.log(test);// {a:2}
コンストラクタがリセットキーを持っていますが、戻り値がない場合は、thisはまだnew fn()に戻る新しいオブジェクトを指します. function fn() {
this.a = 2;
return ;
}
var test = new fn();
console.log(test);// {a: 2}
コンストラクタにリセットキーがあり、オブジェクトを返します.この時点では新しいオブジェクトは生成されません.testの値は、返ってくるobjオブジェクトです. function fn() {
this.a = 2;
return obj;
}
var test = new fn();
console.log(test);// {a: 1}
callとappyメソッドの間接呼び出し関数の本生も対象です.各関数にはcall()とappy()の方法があります.それらを使って、関数を間接的に呼び出すことができます.call()とappy()は、this指向を変えることができます.二つの方法の役割は同じですが、パラメータリストが異なるだけです.call()とappy()は、チルのもう一つの文章「call()とappy()を深く理解する」を見ることができます.
var obj = {};
function sum(x, y){
return x + y;
}
console.log(sum.call(obj,1,2));// 3
console.log(sum.apply(obj,[1,3]));// 4
参考:阮一峰先生の文章:http://javascript.ruanyifeng.com/grammar/function.html 他の優れた文章:http://www.cnblogs.com/xiaohuochai/p/5702813.html#anchor1