1. 程式人生 > >jquery中apply與call的使用

jquery中apply與call的使用

每一個Function物件都有一個apply()方法和一個call()方法

A物件有一個方法,而B物件因為某種不可言說的情況也需要用到一樣的方法,那麼這時候我們是單獨為B擴充套件個方法呢,還是借用一下A的方法呢?當然是借用A的啦,既完成了需求,又減少了記憶體的佔用

apply:呼叫一個物件的一個方法,用另一個物件替換當前物件。例如:B.apply(A, arguments);即A物件應用B物件的方法。

function.apply(obj[,argArray])

只接收兩個引數,其中第二個引數必須是一個陣列或者類陣列,這也是這兩個方法很重要的一個區別

call:呼叫一個物件的一個方法,用另一個物件替換當前物件。例如:B.call(A, args1,args2);即A物件呼叫B物件的方法。

function.call(obj[,arg1[, arg2[, [,.argN]]]]])
  • 呼叫call的物件必須是個函式function
  • call的第一個引數將會是function改變上下文後指向的物件,如果不傳,將會預設是全域性物件window
  • 第二個引數開始可以接收任意個引數,這些引數將會作為function的引數傳入function
  • 呼叫call的方法會立即執行
function add(a,b){
  return a+b;  
}
function sub(a,b){
  return a-b;  
}
var a1 = add.apply(sub,[4,2]);  //sub呼叫add的方法
var a2 = sub.apply(add,[4,2]);
alert(a1);  //6     
alert(a2);  //2

/*call的用法*/
var a1 = add.call(sub,4,2);

異同

相同點

都能夠改變方法的執行上下文(執行環境),將一個物件的方法交給另一個物件來執行,並且是立即執行.

一般來說,this總是指向呼叫某個方法的物件,但是使用call()和apply()方法時,就會改變this的指向。

   var Pet = {
        words : '...',
        speak : function (say) {
            console.log(say + ''+ this.words)
        }
    }
    Pet.speak('Speak'); // 結果:Speak...

    var Dog = {
        words:'Wang'
    }

    //將this的指向改變成了Dog
    Pet.speak.call(Dog, 'Speak'); //結果: SpeakWang
--------------------- 
    function Pet(words){
        this.words = words;
        this.speak = function () {
            console.log( this.words)
        }
    }
    function Dog(words){
        //Pet.call(this, words); //結果: Wang
       Pet.apply(this, arguments); //結果: Wang
    }
    var dog = new Dog('Wang');
    dog.speak();
--------------------- 

不同點

call方法從第二個引數開始可以接收任意個引數,每個引數會對映到相應位置的func的引數上,可以通過引數名呼叫,但是如果將所有的引數作為陣列傳入,它們會作為一個整體對映到func對應的第一個引數上,之後引數都為空

function func (a,b,c) {}

func.call(obj, 1,2,3)
// function接收到的引數實際上是 1,2,3

func.call(obj, [1,2,3])
// function接收到的引數實際上是 [1,2,3],undefined,undefined

apply方法最多隻有兩個引數,第二個引數接收陣列或者類陣列,但是都會被轉換成類陣列傳入func中,並且會被對映到func對應的引數上

func.apply(obj, [1,2,3])
// function接收到的引數實際上是 1,2,3

func.apply(obj, {
    0: 1,
    1: 2,
    2: 3,
    length: 3
})
// function接收到的引數實際上是 1,2,3

兩個方法該如何選擇?

跟簡單,根據你要傳入的引數來做選擇,不需要傳參或者只有1個引數的時候,用call,當要傳入多個物件時,用apply

或者,如果需要傳入的引數已經是一個數組或者類陣列了,就用apply,如果還是單獨的需要逐個傳入的,可以考慮使用call(如果你不嫌麻煩的話 )

jquery中apply的使用

(function (window, $, undefined) {


        //  定義 通用工具方法 擴充套件物件基元
        coreUtil = function () { return Object.apply(this, arguments); },
        //  定義 jQuery 擴充套件物件基元
        coreJquery = function () { return $.apply(this, arguments); },
    coreUtil.fn = coreUtil.prototype = {};
    coreJquery.fn = coreJquery.prototype = {};
    coreJquery.util = coreUtil;

    //  獲取當前頁面 url 引數。
    //  返回值:該方法返回一個數組,陣列中的每個元素都是一個 JSON 物件,該 JSON 物件包含如下屬性:
    //      name:   表示 url 引數的名稱;
    //      value:  表示 url 引數的值;
    //  也可以通過陣列訪問器快速訪問某個特定名稱的引數值,方法如:coreUtil.getRequest()["id"]。
    coreUtil.getRequest = function () {
        var search = location.search;
        if (search.substr(0, 1) == "?") { search = search.substr(1, search.length - 1); }
        var result = [];
        if (search.length > 0) {
            var params = search.split("&");
            for (var i = 0; i < params.length; i++) {
                var param = params[i];
                var pos = param.indexOf("=");
                var name = param.substring(0, pos);
                var value = param.substr(pos + 1);
                result.push({ name: name, value: value });
                result[name] = value;
            }
        }
        return result;
    };
    coreUtil.request = coreUtil.getRequest();
})(window, jQuery);


var url = "approve.html?s=" + Math.random()+"&installApplyId="+rows[0].installApplyId;
  var installApplyId = $.util.request.installApplyId;




jquery中call的使用

        var dgOpts = $.extend({},
            opts.dgOpts,
            {
                onBeforeLoad: function (paras) {
                    if (opts.dgOpts.onBeforeLoad && $.isFunction(opts.dgOpts.onBeforeLoad))
                        opts.dgOpts.onBeforeLoad.call(this, paras);

                    var v = $Core.util.QueryFormSerializeString(searchForm);
                    paras.querystr = v;
                },
                onSelect: function (index, row) {
                    if (opts.dgOpts.onSelect && $.isFunction(opts.dgOpts.onSelect))
                        opts.dgOpts.onSelect.call(this, index, row);

                    if (opts.onSelect && $.isFunction(opts.onSelect)) {

                        var v = opts.onSelect.call(this, index, row);
                        if (v !== false)
                            dialog.dialog("close");
                    }
                }
            });
        grid.datagrid(dgOpts);
		$("#listAdd").bind("click", function() {
			
			if(flag){
				
				$("#listAdd").gridselect({
				    title:'裝置資訊',
				    dialogWidth: '600', //視窗寬度 預設值600
				    dialogHeight: "400",//視窗高度 預設值 70%
				    searchFields: [  //搜尋條件
	    		        {
	    		            name: "deviceName", //separator 指定後會換行顯示
	    		            text: "裝置名稱",
	    		            type: "combobox",  //控制元件型別 只支援 簡單的表單控制元件 textbox my97 combobox 等簡單控制元件 如果條件過多 可以增加 separator 換行顯示
	    		            url: "system/dic/getDicByCode/installdevName",          //字典獲取路徑
	    		            width: '',   //寬度
	    		            querytype: "eq",
	    		            //hidden: true, //是否隱藏域 預設否
	    		            value: '' //預設值
	    		        }, 
	    		        {
	    		            name: "stockDeviceState", //separator 指定後會換行顯示
	    		            text: "狀態",
	    		            type: "textbox",  //控制元件型別 只支援 簡單的表單控制元件 textbox my97 combobox 等簡單控制元件 如果條件過多 可以增加 separator 換行顯示
	    		            //url: "system/dic/getDicByCode/material_type",          //字典獲取路徑
	    		            width: '',   //寬度
	    		            querytype: "like",
	    		            hidden: true, //是否隱藏域 預設否
	    		            value: "1" //預設值
	    		        }
	    		       
	    		    ],
				    dgOpts: { //datagrid 引數
				        url: 'security/devicestock/query',
				      /*  queryParams: {
				    		qqq	: '[{"name":"gfy","value":"'+$("#gfyId").val()+'","type":"like"}]',
				    		d:'fff'
				    	},*/
				    	/*onBeforeLoad:function(paras){
				    		 paras.querystra +="&id="+$("#gfyId").val();
				    	},*/
				        columns: [[
				            {field:'deviceName',title:'裝置名稱',align:'center',width:200,formatter:function (value,row,index) {
		                           return $Core.DicCache.get("installdevName")[value];
		                       }},
				            {field:'deviceNumber',title:'裝置編號',align:'center',width:200},
				            {field:'assetNumber',title:'資產編號',align:'center',width:200},
				            {field:'gfyId',title:'使用使用者',align:'center',width:200,formatter:function(value,row,index) {
				                return $Core.DicCache.get("publicserviceName")[value];
				            }},
				            {field:'productCompany',title:'生產廠家',align:'center',width:200},
				            {field:'stockDeviceState',title:'裝置狀態',align:'center',width:200,formatter:function(value,row,index) {
				            	return $Core.DicCache.get("stockDeviceState")[value];
				            }},
									        ]]
									    },
				    //選擇一行時 被呼叫 return false 不會關掉視窗
				    onSelect: function (index, row) {
				    	
				    	var newRow = {};
				    	newRow.deviceId = row.stockId;
				    	newRow.deviceName = row.deviceName;
				    	newRow.assetsNumber = row.assetNumber;
				    	newRow.deviceNumber = row.deviceNumber;
				    	newRow.deviceSpec = row.standardModel;
				    	newRow.propertyAscription = "1";
				    	newRow.company = "";
				        var stockId = row.stockId;
				        var isAppend = true;
				        $.each($("#dglist2").datagrid("getRows"), function (j,k) {
				            if (k.deviceId==stockId) {
				                isAppend = false;
				            }
				        });
				        if (isAppend) {
				            $("#dglist2").datagrid("appendRow", newRow); 
				        }
				        return false;},
				    onClear: function () { //點選清空按鈕時被呼叫
				    	
				    }
				});
				flag = false;
			}	
			$("#listAdd").gridselect("show");
			
		});

 

 

【其他用途——物件繼承】

由於可以改變this的指向,所以也就可以實現物件的繼承

function superClass () {
    this.a = 1;
    this.print = function () {
        console.log(this.a);
    }
}

function subClass () {
    superClass.call(this);
    this.print();
}

subClass();
// 1

subClass通過call方法,繼承了superClassprint方法和a變數,同時subClass還可以擴充套件自己的其他方法