函数调用的方法一共有 4 种,call,apply,bind
1. 每个函数都包含两个非继承而来的方法:call()方法和apply()方法。
2. 相同点:这两个方法的作用是一样的。
都是在特定的作用域中调用函数,等于设置函数体内this对象的值,以扩充函数赖以运行的作用域。
一般来说,this总是指向调用某个方法的对象,但是使用call()和apply()方法时,就会改变this的指向。
不同点:接收参数的方式不同。
- apply()方法 接收两个参数,一个是函数运行的作用域(this),另一个是参数数组。
语法:apply([thisObj [,argArray] ]);,调用一个对象的一个方法,2另一个对象替换当前对象。
说明:如果argArray不是一个有效数组或不是arguments对象,那么将导致一个
TypeError,如果没有提供argArray和thisObj任何一个参数,那么Global对象将用作thisObj。
- call()方法 第一个参数和apply()方法的一样,但是传递给函数的参数必须列举出来。
语法:call([thisObject[,arg1 [,arg2 [,...,argn]]]]);,应用某一对象的一个方法,用另一个对象替换当前对象。
说明: call方法可以用来代替另一个对象调用一个方法,call方法可以将一个函数的对象上下文从初始的上下文改变为thisObj指定的新对象,如果没有提供thisObj参数,那么Global对象被用于thisObj。
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.apply(a,[1,2]) // 3
var b = a.fn;
b.call(a,1,2) // 3var b = a.fn;
b.bind(a,1,2)()
函数调用的方法一共有 4 种
- 作为一个函数调用
- 函数作为方法调用
- 使用构造函数调用函数
- 作为函数方法调用函数(call、apply)
作为一个函数调用
比如上面的 例 1: 例 1:
var name = "windowsName";
function a() {
var name = "Cherry";
console.log(this.name); // windowsName
console.log("inner:" + this); // inner: Window
}
a();
console.log("outer:" + this) // outer: Window
这样一个最简单的函数,不属于任何一个对象,就是一个函数,这样的情况在 JavaScript 的在浏览器中的非严格模式默认是属于全局对象 window 的,在严格模式,就是 undefined。
但这是一个全局的函数,很容易产生命名冲突,所以不建议这样使用。
函数作为方法调用
所以说更多的情况是将函数作为对象的方法使用。比如例 2: 例 2:
var name = "windowsName";
var a = {
name: "Cherry",
fn : function () {
console.log(this.name); // Cherry
}
}
a.fn();
这里定义一个对象 a,对象 a 有一个属性(name)和一个方法(fn)。
然后对象 a 通过 . 方法调用了其中的 fn 方法。
然后我们一直记住的那句话“this 永远指向最后调用它的那个对象”,所以在 fn 中的 this 就是指向 a 的。
使用构造函数调用函数
如果函数调用前使用了 new 关键字, 则是调用了构造函数。 这看起来就像创建了新的函数,但实际上 JavaScript 函数是重新创建的对象:
// 构造函数:
function myFunction(arg1, arg2) {
this.firstName = arg1;
this.lastName = arg2;
}
// This creates a new object
var a = new myFunction("Li","Cherry");
a.lastName; // 返回 "Cherry"
这就有要说另一个面试经典问题:new 的过程了,(ಥ_ಥ) 这里就简单的来看一下 new 的过程吧: 伪代码表示:
var a = new myFunction("Li","Cherry");
new myFunction{
var obj = {};
obj.__proto__ = myFunction.prototype;
var result = myFunction.call(obj,"Li","Cherry");
return typeof result === 'obj'? result : obj;
}
- 创建一个空对象 obj;
- 将新创建的空对象的隐式原型指向其构造函数的显示原型。
- 使用 call 改变 this 的指向
- 如果无返回值或者返回一个非对象值,则将 obj 返回作为新对象;如果返回值是一个新对象的话那么直接直接返回该对象。
所以我们可以看到,在 new 的过程中,我们是使用 call 改变了 this 的指向。
作为函数方法调用函数
在 JavaScript 中, 函数是对象。
JavaScript 函数有它的属性和方法。 call() 和 apply() 是预定义的函数方法。 两个方法可用于调用函数,两个方法的第一个参数必须是对象本身
在 JavaScript 严格模式(strict mode)下, 在调用函数时第一个参数会成为 this 的值, 即使该参数不是一个对象。 在 JavaScript 非严格模式(non-strict mode)下, 如果第一个参数的值是 null 或 undefined, 它将使用全局对象替代。
这个时候我们再来看例 6: 例 6:
var name = "windowsName";
function fn() {
var name = 'Cherry';
innerFunction();
function innerFunction() {
console.log(this.name); // windowsName
}
}
fn()
这里的 innerFunction() 的调用是不是属于第一种调用方式:作为一个函数调用(它就是作为一个函数调用的,没有挂载在任何对象上,所以对于没有挂载在任何对象上的函数,在非严格模式下this 就是指向 window 的)
然后再看一下 例 7: 例 7:
var name = "windowsName";
var a = {
name : "Cherry",
func1: function () {
console.log(this.name)
},
func2: function () {
setTimeout( function () {
this.func1()
},100 );
}
};
a.func2() // this.func1 is not a function
这个简单一点的理解可以理解为“匿名函数的 this 永远指向 window”,你可以这样想,还是那句话this 永远指向最后调用它的那个对象,那么我们就来找最后调用匿名函数的对象,这就很尴尬了,因为匿名函数名字啊,笑哭,所以我们是没有办法被其他对象调用匿名函数的。所以说 匿名函数的 this 永远指向 window。
如果这个时候你要问,那匿名函数都是怎么定义的,首先,我们通常写的匿名函数都是自执行的,就是在匿名函数后面加 () 让其自执行。其次就是虽然匿名函数不能被其他对象调用,但是可以被其他函数调用啊,比如例 7 中的 setTimeout。
函数调用的方法一共有 4 种,call,apply,bind的更多相关文章
- HTTP的请求方法一共有9种,有OPTIONS, HEAD, GET, POST等等(消息头有图,十分清楚)
请求方法:指定了客户端想对指定的资源/服务器作何种操作 下面我们介绍HTTP/1.1中可用的请求方法: [GET:获取资源] GET方法用来请求已被URI识别的资源.指定的资源经服务器端解析后 ...
- 【转】Java中字符串中子串的查找共有四种方法(indexof())
原文网址:http://wfly2004.blog.163.com/blog/static/1176427201032692927349/ Java中字符串中子串的查找共有四种方法,如下:1.int ...
- Java中字符串中子串的查找共有四种方法(indexof())
Java中字符串中子串的查找共有四种方法(indexof()) Java中字符串中子串的查找共有四种方法,如下:1.int indexOf(String str) :返回第一次出现的指定子字符串在此字 ...
- [Effective JavaScript 笔记]第18条:理解函数调用、方法调用及构造函数调用之间的不同
面向对象编程中,函数.方法.类的构造函数是三种不同的概念. JS中,它们只是单个构造对象的三种不同的使用模式. 三种不同的使用模式 函数调用 function hello(username){ ret ...
- 第164天:js方法调用的四种模式
js方法调用的四种模式 1.方法调用模式 function Persion() { var name1 = "itcast", age1 = 19, show1 = functio ...
- main方法中声明8种基本数据类型的变量并赋值
main方法中声明8种基本数据类型的变量并赋值 char→ int→ long→ float→ double byte→ short→
- 【组合数学+动态规划】在如下8*6的矩阵中,请计算从A移动到B一共有____种走法。要求每次只能向上或向右移动一格,并且不能经过P。
在如下8*6的矩阵中,请计算从A移动到B一共有__种走法.要求每次只能向上或向右移动一格,并且不能经过P. A:456 B:492 C:568 D:626 E:680 F:702 解析: 8*6的矩阵 ...
- 十二、C# 委托与Lambda表达式(匿名方法的另一种写法)
委托与Lambda表达式 1.委托概述 2.匿名方法 3.语句Lambda 4.表达式Lambda 5.表达式树 一.委托概述 相当于C++当中的方法指针,在C#中使用delegate 委托来 ...
- Android开发之去掉标题栏的三种方法,推荐第三种
Android:去掉标题栏的三种方法和全屏的三种方法 第一种:一般入门的时候常常使用的一种方法 onCreate函数中增加下面代码: requestWindowFeature(Window.FEATU ...
随机推荐
- 转移 Visual Studio 2017 的安装临时文件
每次更新 Visual Studio 2017 会在 C 盘留下大量的缓存文件,因为目录比较深,怕以后忘了,用目录链接的形式转移到其它磁盘,也好方便清理: mklink /D C:\ProgramDa ...
- Serializable接口
Serializable这个接口起啥作用呢?? 这个接口没有提供任何方法,我们实现它有什么意义呢? Serializable接口是启用其序列化功能的接口.Serializable接口中没有任何方法,一 ...
- Microsoft.Identity的IPasswordHasher加密的默认实现与运用
本文版权归博客园和作者吴双本人共同所有,转载和爬虫请注明原文地址 www.cnblogs.com/tdws 相信了解了MS Identity认证体系的一定知道UserManager的作用,他是整个体 ...
- System.Runtime.InteropServices.COMException 检索COM类工厂中CLSID{xxxxxxxxx}的组件时失败解决方法
iis7.5中设定应用程序池中<进程模型>中<标识>为localSystem 提示:System.Runtime.InteropServices.COMException: 命 ...
- [React] 06 - Route: koa makes your life easier
听说koa比express更傻瓜化,真的? Koa 框架教程 本身代码只有1000多行,所有功能都通过插件实现,很符合 Unix 哲学. 搭建简单服务器 Koa, 架设一个简单的服务器 // demo ...
- vue.js 开发文档
一.安装 node.js 首先需要安装node环境,可以直接到中文官网http://nodejs.cn/下载安装包. 只是这样安装的 node 是固定版本的,如果需要多版本的 node,可以使用 nv ...
- 通信原理之UDP协议(四)
1.UDP简要介绍 UDP是传输层协议,和TCP协议处于一个分层中,但是与TCP协议不同,UDP协议并不提供超时重传,出错重传等功能,也就是说其是不可靠的协议. 2.UDP协议头 2.1.UDP端口号 ...
- python中getcwd()方法慎用
比如我们想要获取当前目录的路径,有人可能会用到getcwd()方法,但是会发现这个方法有时候不好用.下面介绍一下,getcwd()方法的具体细节: 1.os.getcwd():获取当前工作目录,也就是 ...
- 关于git CRLF LF结尾的问题
在使用git的过程中,如果我们的项目是跨平台开发的 那么CRLF的处理也许会成为一个很头疼的事情,有可能会出以下的莫名其妙的问题: 我们的某个开发人员在linux上提交的一个文件 当从windows上 ...
- 解决Error:All flavors must now belong to a named flavor dimension. Learn more at https://d.android.com
主app的build.gradle里面的 defaultConfig { targetSdkVersion:*** minSdkVersion :*** versionCode:*** version ...