亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

JavaScript函數的4種調用方法詳解

2019-11-20 20:48:11
字體:
來源:轉載
供稿:網友

在JavaScript中,函數是一等公民,函數在JavaScript中是一個數據類型,而非像C#或其他描述性語言那樣僅僅作為一個模塊來使用。函數有四種調用模式,分別是:函數調用形式、方法調用形式、構造器形式、以及apply形式。這里所有的調用模式中,最主要的區別在于關鍵字 this 的意義,下面分別介紹這個幾種調用形式。

本文主要內容:

1.分析函數的四種調用形式
2.弄清楚函數中this的意義
3.明確構造函對象的過程
4.學會使用上下文調用函數

一、函數調用形式

函數調用形式是最常見的形式,也是最好理解的形式。所謂函數形式就是一般聲明函數后直接調用即是。例如:

復制代碼 代碼如下:

// 聲明一個函數,并調用
function func() {
    alert("Hello World");
}
func();

或者:
復制代碼 代碼如下:

// 使用函數的Lambda表達式定義函數,然后調用
var func = function() {
    alert("你好,程序員");
};
func();

這兩段代碼都會在瀏覽器中彈出一個對話框,顯示字符串中的文字,這個就是函數調用。

可以發現函數調用很簡單,就是平時學習的一樣,這里的關鍵是,在函數調用模式中,函數里的 this 關鍵字指全局對象,如果在瀏覽器中就是 window 對象。例如:

復制代碼 代碼如下:

var func = function() {
    alert(this);
};
func();

此時,會彈出對話框,打印出 [object Window]。

二、方法調用模式

函數調用模式很簡單,是最基本的調用方式。但是同樣的是函數,將其賦值給一個對象的成員以后,就不一樣了。將函數賦值給對象的成員后,那么這個就不在稱為函數,而應該叫做方法。例如:

復制代碼 代碼如下:

// 定義一個函數
var func = function() {
    alert("我是一個函數么?");
};
// 將其賦值給一個對象
var o = {};
o.fn = func; // 注意這里不要加圓括號
// 調用
o.fn();

此時,o.fn 則是方法,不是函數了。實際上 fn 的方法體與 func 是一模一樣的,但是這里有個微妙的不同??聪旅娴拇a:
復制代碼 代碼如下:

// 接上面的代碼
alert(o.fn === func);
打印結果是true,這個表明兩個函數是一樣的東西,但是修改一下函數的代碼:

// 修改函數體
var func = function() {
    alert(this);
};
var o = {};
o.fn = func;
// 比較
alert(o.fn === func);
// 調用
func();
o.fn();


這里的運行結果是,兩個函數是相同的,因此打印結果是 true。但是由于兩個函數的調用是不一樣的,func 的調用,打印的是 [object Window],而 o.fn 的打印結果是 [object Object]。

這里便是函數調用與方法調用的區別,函數調用中,this 專指全局對象 window,而在方法中 this 專指當前對象,即 o.fn 中的 this 指的就是對象o。

三、構造器調用模式

同樣是函數,在單純的函數模式下,this 表示 window;在對象方法模式下,this 指的是當前對象。除了這兩種情況,JavaScript 中函數還可以是構造器。將函數作為構造器來使用的語法就是在函數調用前面加上一個 new 關鍵字。如代碼:

復制代碼 代碼如下:

// 定義一個構造函數
var Person = function() {
    this.name = "程序員";
    this.sayHello = function() {
        alert("你好,這里是" + this.name);
    };
};
// 調用構造器,創建對象
var p = new Person();
// 使用對象
p.sayHello();

上面的案例首先創建一個構造函數Person,然后使用構造函數創建對象p。這里使用 new 語法。然后在使用對象調用sayHello()方法,這個使用構造函數創建對象的案例比較簡單。從案例可以看到,此時 this 指的是對象本身。除了上面簡單的使用以外,函數作為構造器還有幾個變化,分別為:

1、所有需要由對象使用的屬性,必須使用 this 引導;

2、函數的 return 語句意義被改寫,如果返回非對象,就返回this。

構造器中的 this

我們需要分析創建對象的過程,方能知道 this 的意義。如下面代碼:

復制代碼 代碼如下:

var Person = function() {
    this.name = "程序員";
};
var p = new Person();

這里首先定義了函數 Person,下面分析一下整個執行:

1、程序在執行到這一句的時候,不會執行函數體,因此 JavaScript 的解釋器并不知道這個函數的內容。

2、接下來執行 new 關鍵字,創建對象,解釋器開辟內存,得到對象的引用,將新對象的引用交給函數。

3、緊接著執行函數,將傳過來的對象引用交給 this。也就是說,在構造方法中,this 就是剛剛被 new 創建出來的對象。

4、然后為 this 添加成員,也就是為對象添加成員。

5、最后函數結束,返回 this,將 this 交給左邊的變量。

分析過構造函數的執行以后,可以得到,構造函數中的 this 就是當前對象。

構造器中的 return

在構造函數中 return 的意義發生了變化,首先如果在構造函數中,如果返回的是一個對象,那么就保留原意。如果返回的是非對象,比如數字、布爾和字符串,那么就返回 this,如果沒有 return 語句,那么也返回 this,看下面代碼:

復制代碼 代碼如下:

// 返回一個對象的 return
var ctr = function() {
    this.name = "趙曉虎";
    return {
        name:"牛亮亮"
    };
};
// 創建對象
var p = new ctr();
// 訪問name屬性
alert(p.name);

執行代碼,這里打印的結果是”牛亮亮”。因為構造方法中返回的是一個對象,那么保留 return 的意義,返回內容為 return 后面的對象,再看下面代碼:
復制代碼 代碼如下:

// 定義返回非對象數據的構造器
var ctr = function() {
    this.name = "趙曉虎";
    return "牛亮亮";
};
// 創建對象
var p = new ctr();
// 使用
alert(p);
alert(p.name);

代碼運行結果是,先彈窗打印[object Object],然后打印”趙曉虎”,因為這里 return 的是一個字符串,屬于基本類型,那么這里的 return 語句無效,返回的是 this 對象,因此第一個打印的是[object Object]而第二個不會打印 undefined。

四、apply調用模式

除了上述三種調用模式以外,函數作為對象還有 apply 方法與 call 方法可以使用,這便是第四種調用模式,我稱其為 apply 模式。

首先介紹 apply 模式,首先這里 apply 模式既可以像函數一樣使用,也可以像方法一樣使用,可以說是一個靈活的使用方法。首先看看語法:函數名.apply(對象, 參數數組);

這里看語法比較晦澀,還是使用案例來說明:

1、新建兩個 js 文件,分別為”js1.js”與”js2.js”;

2、添加代碼

復制代碼 代碼如下:

// js1.js 文件中
var func1 = function() {
    this.name = "程序員";
};
func1.apply(null);
alert(name);

// js2.js 文件
var func2 = function() {
    this.name = "程序員";
};
var o = {};
func2.apply(o);
alert(o.name);

3、分別運行著兩段代碼,可以發現第一個文件中的 name 屬性已經加載到全局對象 window 中; 而第二個文件中的 name 屬性是在傳入的對象 o 中,即第一個相當于函數調用,第二個相當 于方法調用。

這里的參數是方法本身所帶的參數,但是需要用數組的形式存儲在,比如代碼:

復制代碼 代碼如下:

// 一個數組的例子
var arr1 = [1,2,3,[4,5],[6,7,8]];
// 將其展開
var arr2 = arr1.conact.apply([], arr1);
然后介紹一下 call 模式,call 模式與 apply 模式最大的不同在于 call 中的參數不用數組,看下面代碼就清楚了:

// 定義方法
var func = function(name, age, sex) {
    this.name = name;
    this.age = age;
    this.sex = sex;
};
// 創建對象
var o = {};
// 給對象添加成員
// apply 模式
var p1 = func.apply(o, ["趙曉虎", 19, "男"]);
// call 模式
var p2 = func.call(o, "趙曉虎", 19, "男");

上面的代碼,apply 模式與 call 模式的結果是一樣的。

實際上,使用 apply 模式和 call 模式,可以任意的操作控制 this 的意義,在函數 js 的設 計模式中使用廣泛。簡單小結一下,js 中的函數調用有四種模式,分別是:函數式、方法式、構造 器式和 apply 式. 而這些模式中,this 的含義分別為:在函數中 this 是全局對象 window,在方 法中 this 指當前對象,在構造函數中 this 是被創建的對象,在 apply 模式中 this 可以隨意的指定.。在 apply 模式中如果使用 null,就是函數模式,如果使用對象,就是方法模式。

五、綜合例子

下面通過一個案例結束本篇吧。案例說明:有一個div,id為dv,鼠標移到上面去高度增大2倍,鼠標離開恢復,下面直接上js代碼:

復制代碼 代碼如下:

var dv = document.getElementById("dv");
var height = parseInt(dv.style.height || dv.offsetHeight);
var intervalId;
dv.onmouseover = function() {
    // 停止已經在執行的動畫
    clearInterval(intervalId);
    // 得到目標高度
    var toHeight = height * 2;
    // 獲得當前對象
    var that = this;
    // 開器計時器,緩慢變化
    intervalId = setInterval(function() {
        // 得到現在的高度
        var height = parseInt(dv.style.height || dv.offsetHeight);
        // 記錄每次需要變化的步長
        var h = Math.ceil(Math.abs(height - toHeight) / 10);
        // 判斷變化,如果步長為0就停止計時器
        if( h > 0 ) {
            // 這里為什么要用that呢?思考一下吧
            that.style.height = (height + h) + "px";
        } else {
            clearInterval(intervalId);
        }
    }, 20);
};
dv.onmouseout = function() {
    // 原理和之前一樣
    clearInterval(intervalId);
    var toHeight = height;
    var that = this;
    intervalId = setInterval(function() {
        var height = parseInt(dv.style.height || dv.offsetHeight);
        var h = Math.ceil(Math.abs(height - toHeight) / 10);
        if( h > 0 ) {
            that.style.height = (height - h) + "px";
        } else {
            clearInterval(intervalId);
        }
    }, 20);
};

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
国产欧美婷婷中文| 欧美极品美女电影一区| 久热精品在线视频| 38少妇精品导航| 最新亚洲国产精品| 国产日韩欧美在线播放| 亚洲欧美中文字幕| 国产精品国产三级国产aⅴ浪潮| 在线成人一区二区| 插插插亚洲综合网| 亚洲欧洲自拍偷拍| 国产一区二区美女视频| 亚洲国产欧美日韩精品| 亚洲精品美女网站| 欧美极品少妇xxxxx| 欧美特级www| www.色综合| 日韩经典中文字幕| 国产精品一区二区电影| 亚洲国产高清高潮精品美女| 国产午夜精品全部视频播放| 亚洲a∨日韩av高清在线观看| 中文字幕亚洲欧美| 欧美日韩一区二区三区在线免费观看| 国产精品v片在线观看不卡| 91香蕉嫩草神马影院在线观看| 91精品国产九九九久久久亚洲| 成人精品久久一区二区三区| 中文在线不卡视频| 久久久久久久影视| 精品视频在线播放免| 91视频国产精品| 亚洲黄页视频免费观看| 亚洲大胆美女视频| 亚洲在线www| 懂色aⅴ精品一区二区三区蜜月| 日韩免费av一区二区| 久久频这里精品99香蕉| 高清日韩电视剧大全免费播放在线观看| 国产精品丝袜一区二区三区| 欧美激情一二区| 欧美理论电影在线播放| 亚洲成年人在线| 97久久久免费福利网址| 全色精品综合影院| 91精品久久久久久久久青青| 欧美成人亚洲成人日韩成人| 欧美日韩午夜视频在线观看| 亚洲精品视频二区| 欧美亚洲第一区| 中文字幕精品一区久久久久| 丝袜亚洲另类欧美重口| 亚洲经典中文字幕| 在线丨暗呦小u女国产精品| 日韩在线一区二区三区免费视频| 一夜七次郎国产精品亚洲| 日韩免费观看av| 久久久精品2019中文字幕神马| 国产精品自拍偷拍| 亚洲欧美日韩国产中文专区| 亚洲午夜久久久影院| 亚洲精品福利在线观看| 中文字幕国内精品| 亚洲va欧美va国产综合剧情| 日韩中文字幕视频在线观看| 97精品视频在线观看| 中文字幕免费国产精品| 欧美成人免费大片| 亚洲国产精品久久精品怡红院| 91亚洲国产精品| 久久久精品2019中文字幕神马| 色噜噜狠狠狠综合曰曰曰88av| 91免费精品国偷自产在线| 午夜欧美大片免费观看| 亚洲成av人影院在线观看| 欧洲亚洲免费视频| 午夜精品久久久久久久白皮肤| 久久久久久亚洲精品中文字幕| 国模gogo一区二区大胆私拍| 日本一区二三区好的精华液| 91精品国产自产在线老师啪| 日韩精品免费观看| 91久久夜色精品国产网站| 亚洲精品美女在线| 国产午夜一区二区| 亚洲人成网站777色婷婷| 欧美极品少妇全裸体| 成人亚洲激情网| 日韩亚洲欧美成人| 久久久久久久国产精品| 欧美成人一二三| 日韩中文字在线| 一本色道久久88综合亚洲精品ⅰ| 欧美在线性爱视频| 伊人久久久久久久久久久| 日韩最新免费不卡| 久久手机精品视频| 九九九久久国产免费| 亚洲欧美中文字幕| 欧美大片在线看免费观看| 亚洲摸下面视频| 国产精品一区二区在线| 国产精品综合久久久| 久久久在线视频| 久久成人亚洲精品| 欧美亚洲成人xxx| 91影院在线免费观看视频| 欧美日韩在线视频一区二区| 久久亚洲国产精品成人av秋霞| 91国内免费在线视频| 日韩成人在线网站| 久久亚洲精品成人| 九九九久久久久久| 欧洲精品久久久| 日韩av在线网页| 精品国产一区二区三区四区在线观看| 日韩中文第一页| 91精品在线看| 久久综合伊人77777尤物| 中文字幕精品在线| 久久精品99久久香蕉国产色戒| 精品日本高清在线播放| 日本精品久久中文字幕佐佐木| www欧美日韩| 38少妇精品导航| 欧美专区中文字幕| 亚洲在线第一页| 精品亚洲va在线va天堂资源站| 热门国产精品亚洲第一区在线| 久久成人av网站| 91精品视频在线播放| 欧美日韩中文字幕综合视频| 欧美精品中文字幕一区| 久久成人在线视频| 亚洲精品456在线播放狼人| 九九久久国产精品| 国产精品v日韩精品| 日韩中文字幕久久| 亚洲免费视频观看| 丝袜一区二区三区| 国产91免费观看| 国产精品69精品一区二区三区| 久久久久久12| 538国产精品一区二区免费视频| 欧美日韩精品在线| 黄色91在线观看| 久久久电影免费观看完整版| 亚洲999一在线观看www| 久久久久久免费精品| 黑人巨大精品欧美一区二区免费| 九九精品在线视频| 国产精品青草久久久久福利99| 亚洲大尺度美女在线| 久久影视免费观看| 亚洲香蕉成人av网站在线观看| 久久这里只有精品99| 色狠狠久久aa北条麻妃| 成人免费看吃奶视频网站| 国产精品视频永久免费播放| 亚洲精品98久久久久久中文字幕| 国产91在线播放九色快色| 亚洲跨种族黑人xxx| 亚州欧美日韩中文视频| 国产一区二区三区在线看|