1. 程式人生 > >從零開始學 Web 之 JS 高階(三)apply與call,bind,閉包和沙箱

從零開始學 Web 之 JS 高階(三)apply與call,bind,閉包和沙箱

一、apply 和 call 方法

apply 和 call 都可以改變呼叫其的函式或方法中的 this 指向。

不同的是傳入引數時,apply 有兩個引數,第二個引數是陣列;call 從第二個引數開始是呼叫其的函式的所有引數。

使用方法:

1、apply的使用語法:

函式名.apply(物件,[引數1, 引數2,... ]);

方法名.apply(物件,[引數1, 引數2,... ]);

2、call的使用語法:

函式名.call(物件,引數1, 引數2,... );

方法名.call(物件,引數1, 引數2,... );

1、函式呼叫apply和call

function f1(x, y) {
  console.log(x+y +this); // 這裡面的this是window
  return x+y;
}

var r1 = f1.apply(null, [10,20]); // 列印30 window,傳入的是null,所以this指向還是window
console.log(r1); // 30
var r2 = f1.call(null, 10,20);// 列印30 window
console.log(r2); // 30
//函式改變 this 的指向
var obj = {};

var r1 = f1.apply(obj, [10,20]); // 列印30 window,傳入的是Obj,所以this指向是Obj
console.log(r1); // 30
var r2 = f1.call(obj, 10,20);// 列印30 Obj
console.log(r2); // 30

2、方法呼叫apply和call

// 方法改變 this 的指向
    function Person(age) {
        this.age = age;
    }
    Person.prototype.eat = function () {
        console.log(this.age); // this 指向例項物件
    };

    function Student(age) {
        this.age = age;
    }

    var per = new Person(18);
    var stu = new Student(20);

    per.eat.apply(stu); // 列印 20
    per.eat.call(stu); // 列印 20

由於 eat 方法已經指向了 Student 了,所以列印 20,而不是 18.

問題:我們知道函式也是物件,函式可以呼叫 apply 和 call 方法,但是這兩個方法並不在這個函式這個物件的例項函式中,那麼在哪裡呢?

解答:所有的函式都是 Function 的例項物件,而 apply 和 call 就在 Function 建構函式的原型物件中。

二、bind方法

bind 是複製的意思,也可以改變呼叫其的函式或方法的 this 指向,引數可以在複製的時候傳進去,也可以在複製之後呼叫的時候傳進去。

使用語法:

1、函式名.bind(物件, 引數1, 引數2, ...); // 返回值是複製的這個函式

2、方法名.bind(物件, 引數1, 引數2, ...); // 返回值是複製的這個方法

1、函式呼叫 bind

function f1(x, y) {
    console.log(x + y + this);
}
// 1.引數在複製的時候傳入
var ff = f1.bind(null,10,20); // 這只是複製的一份函式,不是呼叫,返回值才是
ff();

// 2.引數在呼叫的時候傳入
var ff = f1.bind(null); // 這只是複製的一份函式,不是呼叫,返回值才是
ff(10,20);

2、方法呼叫 bind

function Person(age) {
    this.age = age;
}

Person.prototype.eat = function () {
    console.log(this.age); // this 指向例項物件
};

function Student(age) {
    this.age = age;
}

var per = new Person(18);
var stu = new Student(20);

var ff = per.eat.bind(stu);
ff(); // 20

bind和call,apply的區別:[update:2018.07.26]

bind繫結this的指向之後,不會立即呼叫當前函式,而是將函式返回。
而call,apply繫結this指向後會立即呼叫。

如果我們在不知道什麼時候會呼叫函式的時候,需要改變this的指向,那麼只能使用bind。

比如:在定時器中,我們想改變this的指向,但是又不能立即執行,需要等待2秒,這個時候只能使用bind來繫結this。

setInterval(function(){
    // ...
}.bind(this), 2000);

三、閉包

1、閉包的概念

有一個函式 A 中有一個函式或者物件 B,那麼函式或者物件 B 可以訪問函式 A 中的資料,那麼函式 A 的作用域就形成了閉包。

2、閉包的模式

函式模式的閉包:函式中包含函式。

物件模式的閉包:函式中包含物件。

3、閉包的作用

快取資料,延長作用域鏈。

4、閉包的優缺點

也是快取的資料,導致在閉包的範圍內一直起作用。

5、閉包的應用

快取資料,函式中的資料,外面可以使用。

如果想要快取資料,就把這個資料放在外層的函式和裡層的函式之間。這樣不停的呼叫裡層函式,相當於外層函式裡的資料沒有得到及時釋放,就相當於快取了資料。

// 函式閉包
function A() {
    var num = 10;
    return function () {
        return num++;
    }
}

var func = A();
console.log(func());
console.log(func());
console.log(func());
// 物件閉包
function A() {
    var num = 10;
    return {
        age: num++
    };
}
var func = A();
console.log(func.age);

四、沙箱

沙箱:一小塊的真實環境,裡面發生的事情不會影響到外面。相同的操作,相同的資料都不會和外面發生衝突。

作用:避免命名衝突。

比如:自呼叫函式裡面就相當於一個沙箱環境。

(function (){
        
}());

五、區分偽陣列和真陣列

// 真陣列
    var arr = [10,20,30];
    // 偽陣列
    var obj = {
        0:10,
        1:20,
        2:30,
        length: 3
    };
    // 真陣列的訪問
    for(var i=0; i<arr.length; i++) {
        console.log("真陣列的訪問:"+arr[i]);
    }
    // 偽陣列的訪問
    for(var j=0; j<obj.length; j++) { // 錯誤:物件中沒有length方法
        console.log("偽陣列的訪問:"+obj[j]);
    }

方法一、使用 length 來區分

這樣看起來,真陣列和偽陣列就沒法區別了。

但是真陣列的長度 length 可以改變,偽陣列不可以,貌似可以區分了。

但是,你還記得有個 arguement 這個偽陣列(物件)的 length 是可以改變的,方法一區分失敗。

方法二、使用陣列的方法 forEach 來鑑別

因為每個陣列都是 Array 的例項物件,而 forEach 在 Array 的原型物件中,所以其他的偽陣列是不能使用的。方法二成功。

相關推薦

開始 Web JS 高階applycallbind沙箱

一、apply 和 call 方法 apply 和 call 都可以改變呼叫其的函式或方法中的 this 指向。 不同的是傳入引數時,apply 有兩個引數,第二個引數是陣列;call 從第二個引數開始是呼叫其的函式的所有引數。 使用方法: 1、apply的使用語法: 函式名.apply(物件,[引數1

開始 Web JS 高階原型鏈原型的繼承

一、原型鏈 原型連結串列示的是例項物件與原型物件之間的一種關係,這種關係是通過__proto__原型來聯絡的。 1、原型的指向改變 例項物件的原型 __proto__ 指向的是該物件的建構函式中的原型物件 prototype,如果該物件的建構函式的 prototype 指向改變了,那麼例項物件中的原型 _

開始 Web JavaScript 高階原型貪吃蛇案例

一、複習 例項物件和建構函式之間的關係: 1、例項物件是通過建構函式來建立的,建立的過程叫例項化。 2、如何判斷一個物件是不是某種資料型別? 通過構造器的方法。例項物件.constructor === 建構函式名字 (推薦使用)例項物件 instanceof 建構函式名字 二、原型 1、原型的引入 由

開始 Web JS 高級原型鏈原型的繼承

console 多少 程序 cat hub inf 當前 構造函數 調用 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:

開始 Web JS 高級applycallbind沙箱

master 操作 console 概念 釋放 分享圖片 成功 num 命名沖突 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔

【高德地圖API】開始高德JS API——定位方式大揭祕

摘要:關於定位,分為GPS定位和網路定位2種。GPS定位,精度較高,可達到10米,但室內不可用,且超級費電。網路定位,分為wifi定位和基站定位,都是通過獲取wifi或者基站資訊,然後查詢對應的wifi或者基站位置資料庫,得到的定位地點。定位資料庫可以不斷完善不斷補充,所以,

轉載:高德地圖API學習 開始高德JS API地圖展現

摘要:關於地圖的顯示,我想大家最關心的就是麻點圖,自定義底圖的解決方案了吧。在過去,marker大於500之後,瀏覽器開始逐漸卡死,大家都開始尋找解決方案,比如聚合marker啊,比如麻點圖啊。聚合marker裡面還有一些複雜的演算法,而麻點圖,最讓大家頭疼的,就是如何生成麻點圖,如何切圖,如何把圖片貼到地圖

webpack開始構建專案rem問題

使用webpack解決px轉rem的自適應問題 現在的專案配置已經可以正常執行 接下來我們要考慮下一個問題,由於VUE主要適用於移動端,所以我們需要一個自適應方案 由於這是一個大眾需求的剛需方案,所以我們大可不必自己手動去寫JS程式碼,重複造輪子 那麼我

開始 Web Vue.jsVue實例的生命周期

報錯 web 前端 cnblogs 前端 eth code vue 公眾 des 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔

開始 Web Vue.jsVue的Ajax請求跨域

在線安裝 配置 name php文件 splay .json alert 參考 1.0 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端

開始 Web Vue.jsVue的動畫

一、Vue的動畫 為什麼要有動畫:動畫能夠提高使用者的體驗,幫助使用者更好的理解頁面中的功能; Vue 中也有動畫,不過遠沒有 css3 中的那麼炫酷。只能有一些簡單的變換,但是卻可以配合第三方css動畫庫完成炫酷的變換。 1、過渡的類名 在進入/離開的過渡

開始 Web Vue.jsVue的元件

大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 部落格園:http://www.cnblogs.com/lvonve/ CSDN:https://blog.csdn.net/lvonve/

開始 Web Vue.js過濾器按鍵修飾符自定義指令

大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 部落格園:http://www.cnblogs.com/lvonve/ CSDN:https://blog.csdn.net/lvonve/

開始 Web Vue.jsVue.js概述基本結構指令事件修飾符樣式

大家好,這裡是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 部落格園:http://www.cnblogs.com/lvonve/ CSDN:https://blog.csdn.net/lvonve/

開始 Web DOMDOM的概念對標簽操作

關註 1.5 pan 什麽 tin p標簽 nod text == 大家好,這裏是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關註。在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相關的知識點,

開始 Web DOM節點

def clas scrip while p標簽 設置 ner 操作 text 大家好,這裏是「 Daotin的夢囈 」從零開始學 Web 系列教程。此文首發於「 Daotin的夢囈 」公眾號,歡迎大家訂閱關註。在這裏我會從 Web 前端零基礎開始,一步步學習 Web 相

開始 Web BOMoffsetscroll變速動畫函數

樣式 清理 java mar dde sof mov har width 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:

開始 Web jQuery獲取操作元素的屬性

eight images idt 隱藏 lis 屬性 ner master lin 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔

開始 Web jQuery為元素綁定多個相同事件解綁事件

png 好用 添加 方式 執行 存在 區別 也會 地址 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客園:http://ww

開始 Web jQuery事件冒泡事件參數對象鏈式編程原理

eval uri turn 定位 return 也會 否則 ont sele 大家好,這裏是「 從零開始學 Web 系列教程 」,並在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公眾號:Web前端之巔 博客