ホームページ > 記事 > ウェブフロントエンド > JS_javascript スキルの呼び出し/適用、引数、未定義/null メソッドの詳細な説明
a.call メソッドと apply メソッドの詳細な説明
-------------------------------------------------- ----------------------------------
呼び出しメソッド:
構文: call([thisObj[,arg1[, arg2[, [,.argN]]]]])
定義: オブジェクトのメソッドを呼び出して、現在のオブジェクトを別のオブジェクトに置き換えます。
注: call メソッドを使用すると、別のオブジェクトの代わりにメソッドを呼び出すことができます。 call メソッドは、関数のオブジェクト コンテキストを初期コンテキストから thisObj で指定された新しいオブジェクトに変更します。 thisObj パラメーターが指定されていない場合は、グローバル オブジェクトが thisObj として使用されます。
適用メソッド:
構文: apply([thisObj[,argArray]])
定義: オブジェクトのメソッドを適用して、現在のオブジェクトを別のオブジェクトに置き換えます。
注: argArray が有効な配列でない場合、または引数オブジェクトではない場合、TypeError が発生します。 argArray も thisObj も指定されていない場合は、Global オブジェクトが thisObj として使用され、パラメータを渡すことはできません。
学習例:
function add(a,b){ alert(a+b);} function sub(a,b){ alert(a-b);} add.call(sub,3,1);
出力された結果は 4 です。 add 関数が呼び出されますが、呼び出し元のオブジェクト (コンテキスト) は add オブジェクトではなく、サブ関数オブジェクトです。注: js の関数は実際にはオブジェクトであり、関数名は Function オブジェクトへの参照です。
function Animal(){ this.name = "Animal"; this.showName = function(){ alert(this.name);} } function Cat(){ this.name = "Cat"; } var animal = new Animal(); var cat = new Cat(); animal.showName.call(cat,",");//输出结果为"Cat" animal.showName.apply(cat,[]);//输出结果为"Cat"
call は、animal のメソッドを cat に置いて実行することを意味し、context は cat です。元々、cat には showName() メソッドがありませんでしたが、現在は、animal の showName() メソッドを cat に置いて実行されています。 .名前は猫です。したがって、this.name は Cat
である必要があります。
継承を実装する
function Animal(name){ this.name = name; this.showName = function(){ alert(this.name);} } function Cat(name){ Animal.call(this, name); } var cat = new Cat("Black Cat"); cat.showName();
Animal.call(this) は Animal メソッドを呼び出すことを意味しますが、Animal オブジェクトの代わりにこのオブジェクトを使用すると、コンテキストは次のようになります。 Animal.call は new Cat("Black Cat") で使用され、現在のコンテキストの属性名とメソッド showName を設定します。
拡張: 多重継承
function Class10(){ this.showSub = function(a,b){ alert(a-b); } } function Class11(){ this.showAdd = function(a,b){ alert(a+b); } } function Class2(){ Class10.call(this); Class11.call(this); }
注: プロトタイプ チェーンを使用するなど、js を継承する他の方法もあります。これは、この記事の範囲外です。ここでは、call の使用法について説明します。 call と apply について言えば、これら 2 つのメソッドは基本的に同じことを意味します。違いは、call の 2 番目のパラメーターは任意の型にできるのに対し、apply の 2 番目のパラメーターは配列または引数でなければならないことです。
b.arguments は
を使用します
----------------------------------------------- --- ----------------------------------
引数とは
引数は JavaScript の組み込みオブジェクトです。奇妙で見落とされがちですが、実際には非常に重要です。すべての主要な JavaScript ライブラリは、arguments オブジェクトを利用します。したがって、agruments オブジェクトは JavaScript プログラマにとって馴染みのあるものでなければなりません。
すべての関数には独自の引数オブジェクトがあり、関数によって呼び出されるパラメータが含まれています。 typeof 引数が使用されている場合は、「object」が返されます。ただし、データを呼び出すメソッドを使用して引数を呼び出すことはできます。たとえば、長さとインデックスのメソッドです。ただし、配列のプッシュおよびポップ オブジェクトは適用できません。
引数を使用して柔軟な関数を作成する
引数オブジェクトの用途は非常に限られているように見えますが、実際には非常に便利なオブジェクトです。引数オブジェクトを使用すると、可変数の引数を使用して関数を呼び出すことができます。 Dean Edwards の Base2 ライブラリには、この柔軟性を示すフォーマット関数があります。
function format(string) { var args = arguments; var pattern = new RegExp('%([1-' + arguments.length + '])', 'g'); return String(string).replace(pattern, function(match, index,position,all) { console.log(match + '&' + index + '&' + position + '&' + all); return args[index]; }); };
Replace format('And the %1 want to know that who %2 you %3', 'papers', 'shirt', 'wear'); 結果は、「そして、新聞はあなたが誰のシャツを着ているかを知りたがっている」になります。 ; コンソールには
と表示されます。
%1&1&8&そして %1 は、あなたが %2 であることを知りたいと思っています
%2&2&30&そして %1 はあなたが誰の %2 かを知りたいと思っています %3
%3&3&37&そして %1 はあなたが誰の %2 かを知りたいと思っています %3
引数オブジェクトを実数の配列に変換します
引数オブジェクトは実際の JavaScript 配列ではありませんが、標準データに簡単に変換して配列操作を実行できます。
var args = Array.prototype.slice.call(arguments);
これで、変数 args には、関数のすべてのパラメーターを含む標準の JavaScript 配列オブジェクトが含まれます。
拡張: 前のセクションの format 関数を使用して、プリセット引数オブジェクトを通じて関数を作成します
function makeFunc() { var args = Array.prototype.slice.call(arguments); var func = args.shift(); return function() { return func.apply(null, args.concat(Array.prototype.slice.call(arguments))); }; }
该方法会将第一个参数取出来,然后返回一个curry化函数,该curry化函数的参数(第二个arguments)将和makeFunc的从第二个参数开始的参数组合成新数组。并返回makeFunc第一个参数的apply调用
执行
var majorTom = makeFunc(format, "This is Major Tom to ground control. I'm %1."); majorTom("stepping through the door");
结果为:"This is Major Tom to ground control. I'm stepping through the door."
控制台打印:%1&1&41&This is Major Tom to ground control. I'm %1.
[function.]arguments.callee
说明:arguments.callee方法返回的是正在执行的函数本身。
callee 属性是 arguments 对象的一个成员,它表示对函数对象本身的引用,这有利于匿名函数的递归或者保证函数的封装性,例如下边示例的递归计算1到n的自然数之和。而该属性仅当相关函数正在执行时才可用。还有需要注意的是callee拥有length属性,这个属性有时候用于验证还是比较好的。arguments.length是实参长度,arguments.callee.length是形参(定义时规定的需要的参数)长度,由此可以判断调用时形参长度是否和实参长度一致。
//用于验证参数 function calleeLengthDemo(arg1, arg2) { if (arguments.length==arguments.callee.length) { window.alert("验证形参和实参长度正确!"); return; } else { alert("实参长度:" +arguments.length); alert("形参长度: " +arguments.callee.length); } } //递归计算 var sum = function(n){ if (n <= 0) return 1; else return n +arguments.callee(n - 1) } //比较一般的递归函数: var sum = function(n){ if (1==n) return 1; else return n + sum (n-1); }
调用时:alert(sum(100));其中函数内部包含了对sum自身的引用,函数名仅仅是一个变量名,在函数内部调用sum即相当于调用一个全局变量,不能很好的体现出是调用自身,这时使用callee会是一个比较好的方法。
拓展 functionName.caller
说明: 返回是谁调用了functionName 函数。functionName 对象是所执行函数的名称。对于函数来说,caller 属性只有在函数执行时才有定义。如果函数是由顶层调用的,那么 caller 包含的就是 null 。如果在字符串上下文中使用 caller 属性,那么结果和 functionName.toString 一样,也就是说,显示的是函数的反编译文本。 下面的例子说明了 caller 属性的用法:
// caller demo { function callerDemo() { if (callerDemo.caller) { var a= callerDemo.caller.toString(); alert(a); } else { alert("this is a top function"); } } function handleCaller() { callerDemo(); } handleCaller();
执行结果:
c.undefined和null
--------------------------------------------------------------------------------
大多数计算机语言,有且仅有一个表示"无"的值,比如,C语言的NULL,Java语言的null,Python语言的none,Ruby语言的nil。有点奇怪的是,JavaScript语言居然有两个表示"无"的值:undefined和null。这是为什么?
相似性
在JavaScript中,将一个变量赋值为undefined或null,老实说,几乎没区别。
代码如下:
var a = undefined; var a = null;
上面代码中,a变量分别被赋值为undefined和null,这两种写法几乎等价。
undefined和null在if语句中,都会被自动转为false,相等运算符甚至直接报告两者相等。
if (!undefined) console.log('undefined is false'); // undefined is false if (!null) console.log('null is false'); // null is false undefined == null // true
上面代码说明,两者的行为是何等相似!但是我们去查看undefined和null的各自的类型却发现类型是不同的。js基础类型中没有null类型
typeof null;//"object" typeof undefined;//"undefined"
既然undefined和null的含义与用法都差不多,为什么要同时设置两个这样的值,这不是无端增加JavaScript的复杂度,令初学者困扰吗?Google公司开发的JavaScript语言的替代品Dart语言,就明确规定只有null,没有undefined!
历史原因
原来,这与JavaScript的历史有关。1995年JavaScript诞生时,最初像Java一样,只设置了null作为表示"无"的值。
根据C语言的传统,null被设计成可以自动转为0。
Number(null) // 0
5 + null // 5
但是,JavaScript的设计者Brendan Eich,觉得这样做还不够,有两个原因。
首先,null像在Java里一样,被当成一个对象。
typeof null // "object"
但是,JavaScript的数据类型分成原始类型(primitive)和合成类型(complex)两大类,Brendan Eich觉得表示"无"的值最好不是对象。
其次,JavaScript的最初版本没有包括错误处理机制,发生数据类型不匹配时,往往是自动转换类型或者默默地失败。Brendan Eich觉得,如果null自动转为0,很不容易发现错误。因此,Brendan Eich又设计了一个undefined。
最初设计
JavaScript的最初版本是这样区分的:null是一个表示"无"的对象,转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。
Number(undefined) // NaN
5 + undefined // NaN
目前的用法
但是,上面这样的区分,在实践中很快就被证明不可行。目前,null和undefined基本是同义的,只有一些细微的差别。
null表示"没有对象",即该处不应该有值。典型用法是:
(1) 作为函数的参数,表示该函数的参数不是对象。
(2) 作为对象原型链的终点。
Object.getPrototypeOf(Object.prototype) // null
undefined表示"缺少值",就是此处应该有一个值,但是还没有定义。典型用法是:
(1)变量被声明了,但没有赋值时,就等于undefined。
(2) 调用函数时,应该提供的参数没有提供,该参数等于undefined。
(3)对象没有赋值的属性,该属性的值为undefined。
(4)函数没有返回值时,默认返回undefined。
var i; i // undefined function f(x){console.log(x)} f() // undefined var o = new Object(); o.p // undefined var x = f(); x // undefined
以上所述是小编给大家介绍的JS中call/apply、arguments、undefined/null方法详解,希望对大家有所帮助。