前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind

在我的职业生涯中,很早就已经开始使用JavaScript进行项目开发了。但是一直都是把重心放在了后端开发方面,前端方面鲜有涉及。所以造成的一个现象就是:目前的前端知识水平,应付一般的项目已然是足够的,但是火候尚缺,没有深入的进行研究,以至于总是谈论起来就发现自己半瓶子哐当的水平。为了解决这种尴尬的局面,决心潜心研究一段时间JavaScript,以下知识为本人学习过程中的总结,虽然以本人水平可能招致贻笑大方之果,但是更盼抛砖引玉之实。

在JavaScript中,我们调用一个普通的方法,可以通过如下的方式来进行:

//全局公共调用方式

function greetingMorning()

{

alert("Hello Morning!");

}

greetingMorning();

//局部调用方式

var greetingWorld =function() {

alert("Hello World!");

} greetingWorld();

//自调用方式

(function(){

alert("Hello ChaoYang!");

})();

那么上面就是一般的三种调用方式,前两种都会在window对象上面进行附加,不同之处就在于,第一种是直接利用function进行声明方式,属于公共调用方式;第二种是利用var关键字进行申明的方式调用。也就是说,第一种申明方式所申明的函数,无论在函数体之前或之后调用,都没问题。而第二种申明方式所申明的函数,只能在函数体之后调用:

//正确,可以这么调用

greetingMorning();

function greetingMorning()

{

alert("Hello Morning!");

}

//错误,提示找不到方法

greetingWorld();

var greetingWorld =function()

{

alert("Hello World!");

}

在这里,我们需要注意的第一个坑就是局部变量加不加var关键字的问题:

function greetingLucy()

{

name ="lucy";

alert("Hello "+name);

}

greetingLucy();

alert(name);

这里我们的执行结果,第一次会输出: Hello lucy, 第二次会输出: lucy。 这很奇怪,为什么name我写到了方法里面,按理来说已经是局部变量了,为什么还是会输出结果呢?其实在JavaScript中,在方法体内,如果不加var关键字的话,会将此变量默认为全局变量。这也是为什么会输出结果的原因了。

那么知道了函数执行的一般方法,那么我们来看函数的执行的特殊方法。

如上所述,我们直接利用 (); 的方式可以出发函数的立即执行。但是这种执行,其实在大多数情况下是无法改变this关键字的作用域的,由于this默认指向的就是已经实例化过的window对象,所以很多时候当我们需要更改this的作用域的时候,我们就不得不引入 apply, call 关键字 以及 bind 关键字。 我们先来讲解他们的基本用法。

首先,对于apply方法:

//不带参数,我们apply了this,可以看出我们改变了this的作用域 //从原本的window对象,指向了greetingLucy

function greetingLucy()

{

var name ="lucy"; alert("Hello "+name);

}

greetingLucy.apply(this);

//带两个参数

function greeting(name, age)

{

alert("Hello "+ name +""+ age +" !");

}

greeting.apply(this,["lucy",23]);

可以看出,使用apply的时候,其中第一个参数一定要指向需要应用的对象,之后的多个参数需要写成数组的方式。

再来看看call方法:

function greetingLucy()

{

var name ="lucy";

alert("Hello "+name);

}

greetingLucy.call(this);

function greeting(name,age)

{

alert("Hello "+ name +""+ age +" !");

}

greeting.call(this,"lucy",25);

可以看出,使用call的时候,第一个参数也是需要指向被调用的对象,之后的多个参数可以直接写就行。

从这里我们可以看出,apply和call都会改变this的作用域,至于更详细的信息,我会放到第二节去讲解。

下面我们来看看bind方法。

var color ="red";

var obj = {color:"blue"};

function sayColor()

{

alert(this.color);

}

var nw = sayColor.bind(obj);

//执行

nw();

这里会输出什么呢? 这里会输出“blue”。那为什么不会输出red呢? 其实在这里,this关键字有个很重要的特点,那就是: 谁调用我,我指向谁。由于bind方法的调用,会导致this指向的改变,从window对象变成了指向obj对象。所以这里会拿obj对象中的color来执行。

从上面的例子我们也可以看出,bind方法不会导致函数的立即执行,需要触发才可以执行。

为什么bind不会立即执行呢? 我们可以执行 alert(nw)看出返回给我们的结果:

function bound sayColor(){[native code]}

这说明bind以后返回的nw对象,就是一个函数,并且还是未执行的函数,如果我们想执行,就需要加上 ();

好了,这里就是我所理解的 apply call bind的用法了。

其实他们的用法很基础,但是他们可以改变this作用域的这个特点倒是杀伤力惊人。后面的章节我会重点讲解this,争取将其吃透。敬请期待。

时间: 2024-12-23 09:21:41

前端见微知著JavaScript基础篇:你所不知道的apply, call 和 bind的相关文章

前端见微知著JavaScript基础篇:this or that ?

上节,我们提到了this关键字的问题,并且追加了一句很有意义的话:谁调用我,我指向谁.的确,在javascript中,在默认情况下,this会指向一个已经初始化的window对象.所以你不论有多少全局变量,全局函数,默认都是追加到window对象上,所以在这种情况下无论怎么使用this,都是在这个window对象上去查找各种变量,函数等. 在实际编码中,this的默认情况只能适用于业务比较简单的场景中.但是在大部分业务场景中,this都需要改变其指向来实现一定的业务逻辑.这样一来,我们就得来好好

【javascript杂谈】你所不知道的replace函数

原文:[javascript杂谈]你所不知道的replace函数 前言 最近在做面试题的时候总会用到这个函数,这个函数总是和正则表达式联系到一起,并且效果很是不错,总能很简单出色的完成字符串的实际问题,大家肯定都会使用这个函数,像我一样的初学者可能对这个函数的了解还是不够深的,今天就总结一下,了解一下,再做几道网上的题目练练手,给将要面试的同学打打气. 介绍 使用一个替换值替换掉一个替换模式在原字符串中一个或所有的匹配项,并返回替换后的字符串,这个替换模式可以是字符串或者正则表达式,替换值可以是

C#线程篇---你所不知道的线程池(4)

线程的创建和销毁都要耗费大量的时间,有什么更好的办法?用线程池! 太多的线程浪费内存资源,有什么更好的办法?用线程池! 太多线程有损性能,有什么更好的办法?用线程池!(⊙_⊙)? 线程池是什么?继前三篇线程基础之后,我们要来学学线程池了.注意,这些信息相当有用! 为了设计和实现可伸缩的.可响应的和可靠的应用程序或组建,线程池是你必须采用的核心技术. 线程池是CLR的,线程池自动为你管理线程的创建和销毁,线程池创建的一组线程将为各种任务而重用,极大提高了使用线程的成本,这也就意味着,你的应用程序其

JavaScript中你所不知道的Object(二)--Function篇

上一篇(JavaScript中你所不知道的Object(一))说到,Object对象有大量的内部属性,而其中多数和外部属性的操作有关.最后留了个悬念,就是Boolean.Date.Number.String.Function等有更多的内部属性,而它们分别是什么呢? 这些内部属性不能像Object的内部属性一样一言以蔽之,因为它们各有各的用处和特点.其中核心的部分自然是最特殊的对象,Function对象.我们先从简单的开始: [[PrimitiveValue]]: 值的类型是基础数据类型.所以所有

你所不知道的JavaScript数组

你所不知道的JavaScript数组 相信每一个 javascript 学习者,都会去了解 JS 的各种基本数据类型,数组就是数据的组合,这是一个很基本也十分简单的概念,他的内容没多少,学好它也不是件难事情.但是本文着重要介绍的并不是我们往常看到的 Array,而是 ArrayBuffer. 我写的很多东西都是因为要完成某些特定的功能而刻意总结的,可以算是备忘,本文也是如此!前段时间一直在研究 Web Audio API 以及语音通信相关的知识,内容侧重于音频流在 AudioContext 各个

你所不知道的html5与html中的那些事第三篇

文章简介: 关于html5相信大家早已经耳熟能详,但是他真正的意义在具体的开发中会有什么作用呢?相对于html,他又有怎样的新的定义与新理念在里面呢?为什么一些专家认为html5完全完成后,所有的工作都可以达到真正的云方式呢?这一系列的问题你是否已经想明白了呢? 本系列文章将为您一一解答你所不知道的关于html5与html中的那些事;具体会包括如:html5新的理念与想法,html5的新标签的用意与具体开发中场景应用,html5与css3的感情经历(用法搭配),包括html5的父亲html的一些

JavaScript你所不知道的困惑(2)

困惑一: var obj1 = new Object(); var obj2 = obj1; obj1.name = "阳光小强"; alert(obj2.name); //输出结果:阳光小强 JavaScript中的5个基本类型:Undefined.Null.Boolean.Number和String都是按值访问的,可以操作保存在变量中的实际的值,内存空间如下: var num1 = 5; var num2 = num1; 引用类型的值是保存在内存中的对象,JavaScript不允许

JavaScript你所不知道的困惑(1)

困惑一: 先看一个例子: function test(){ message = "hi"; } test(); alert(message); 会输出字符串"hi" 在函数内部使用var定义的变量是局部变量,省略var操作符的变量是全局变量. 困惑二: alert(undefined == null) 结果是"true" 我们知道在js中分为基本类型和引用类型,基本类型包括number.string.boolean.undefined.null.

JavaScript你所不知道的困惑(3)

困惑一: window.color = "red"; var o = {color: "blue"}; function sayColor(){ alert(this.color); } sayColor(); //red sayColor.call(this); //red sayColor.call(window); //red sayColor.call(o); //blue call方法能扩充函数作用域,每个函数都包含两个非继承而来的方法:apply()和c