JavaScript函数的4种调用方法详解
在JavaScript中,函数是一等公民,函数在JavaScript中是一个数据类型,而非像C#或其他描述性语言那样仅仅作为一个模块来使用。函数有四种调用模式,分别是:函数调用形式、方法调用形式、构造器形式、以及apply形式。这里所有的调用模式中,最主要的区别在于关键字 this 的意义,下面分别介绍这个几种调用形式。
本文主要内容:
1.分析函数的四种调用形式
2.弄清楚函数中this的意义
3.明确构造函对象的过程
4.学会使用上下文调用函数
一、函数调用形式
函数调用形式是最常见的形式,也是最好理解的形式。所谓函数形式就是一般声明函数后直接调用即是。例如:
function func() {
alert("Hello World");
}
func();
或者:
var func = function() {
alert("你好,程序员");
};
func();
这两段代码都会在浏览器中弹出一个对话框,显示字符串中的文字,这个就是函数调用。
可以发现函数调用很简单,就是平时学习的一样,这里的关键是,在函数调用模式中,函数里的 this 关键字指全局对象,如果在浏览器中就是 window 对象。例如:
alert(this);
};
func();
此时,会弹出对话框,打印出 [object Window]。
二、方法调用模式
函数调用模式很简单,是最基本的调用方式。但是同样的是函数,将其赋值给一个对象的成员以后,就不一样了。将函数赋值给对象的成员后,那么这个就不在称为函数,而应该叫做方法。例如:
var func = function() {
alert("我是一个函数么?");
};
// 将其赋值给一个对象
var o = {};
o.fn = func; // 注意这里不要加圆括号
// 调用
o.fn();
此时,o.fn 则是方法,不是函数了。实际上 fn 的方法体与 func 是一模一样的,但是这里有个微妙的不同。看下面的代码:
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 的意义。如下面代码:
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,看下面代码:
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、添加代码
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 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);
};
JavaScript函数的4种调用方法详解的更多相关文章
- JavaScript 函数的4种调用方法
JavaScript 函数有 4 种调用方式. 每种方式的不同方式在于 this 的初始化. 作为一个函数调用 function myFunction(a, b) { return a * b; } ...
- javascript中函数的四种调用模式详解
介绍函数四种调用模式前,我们先来了解一下函数和方法的概念,其实函数和方法本质是一样,就是称呼不一样而已.函数:如果一个函数与任何对象关系,就称该函数为函数.方法:如果一个函数作为一个对象属性存在,我们 ...
- javascript 函数的4种调用方式与 this(上下文)的指向
前言:这是笔者学习之后自己的理解与整理.如果有错误或者疑问的地方,请大家指正,我会持续更新! javascript中作用域链和this(上下文)的指向是很容易混淆的,简单的说就是: 作用域链取决于函数 ...
- javascript 函数的4种调用模式
1. 函数模式 // this 指向 window 全局对象 2. 方法模式 // this 指向调用这个方法的对象 3. 构造函数模式 // this 指向 new 新创建出来的实例 4. 上下文模 ...
- JavaScript中数组Array.sort()排序方法详解
JavaScript中数组的sort()方法主要用于对数组的元素进行排序.其中,sort()方法有一个可选参数.但是,此参数必须是函数. 数组在调用sort()方法时,如果没有传参将按字母顺序(字符编 ...
- servlet两种配置方法详解
1.web.xml中Servlet的注解 <servlet> <!-- servlet的内部名称,自定义 --> <servlet-name>DemoAction ...
- iOS中 三种随机数方法详解
ios 有如下三种随机数方法: //第一种 srand((unsigned)time(0)); //不加这句每次产生的随机数不变 int i = rand() % 5; //第二种 srandom(t ...
- javascript this 代表的上下文,JavaScript 函数的四种调用形式
JavaScript 是一种脚本语言,支持函数式编程.闭包.基于原型的继承等高级功能.其中JavaScript 中的 this 关键字,就是一个比较容易混乱的概念,在不同的场景下,this会化身不同的 ...
- javascript函数的4种调用方式
在javascript中一共有4种函数调用模式,分别是:方法调用模式.函数调用模式.构造函数调用模式和apply(call)调用模式,这4种模式的主要差异在于如何初始化关键参数this. 方法调用模式 ...
随机推荐
- CSS学习笔记2-2d变换和过渡属性
前言:今天又是一个周末,心情不错,趁着闲暇之余,把剩下来的CSS3学习的内容全部整理出来,练习用的源码也稍微整理了一下. 2D转换 transform:translate||rotate||scale ...
- uwp如何建立任何形状的头像,如圆形,方形,六边形等
最近掌上英雄联盟更新了新的界面,其中“我”界面的更新比较大,我目前还在加紧跟进.在做这个界面的时候,这个头像我想了一下,其实挺好解决的.先上个原图 这个头像一开始我也完全找不到头绪,然后我把头像放大了 ...
- ClickOnce部署
(1):一些发布方式 ClickOnce是什么玩意儿,这个问题嘛,在21世纪的互联网严重发达的时代,估计也没有必要大费奏章去介绍了,弄不好的话,还有抄袭之嫌.因此,有关ClickOnce的介绍,各位朋 ...
- Android之自定义标题
我们知道我们创建的每一个Activity,系统默认为我们提供了一下黑色的标题,本篇我将带领大家接触一下如何实现自定义标题样式.相比系统为我们提供的样式,自定义标题可以满足我们唯心所欲的自定义设计,使我 ...
- DIV元素水平和垂直居中
在前端开发过程中,经常要对元素进行居中设置.一般有水平居中,和垂直居中.一般设置水平居中简单.基本是margin:0 auto,就可以了.但是垂直居中,我们有时会觉得使用vertical-align, ...
- 使用ikmv将jar转换为dll,在.NET中直接调用
ikmv百科介绍 ikvm官网 使用ikvm前需要先安装java. ikvm的使用比较简单,到官网下载ikvm需要的组件,解压后在path中配置 %IKVM_HOME%\bin 在cmd中使用命令 i ...
- objective-c 语法快速过(1)
有一定 c++或者 java 基础,过一遍 oc 语法即可,都是相通的,个人认为难点是 oc 的内存管理,虽然有了 ARC,但是也需要学习下,因为有旧软件的维护. 建立在C语言的基础上,增加了一层小范 ...
- 【Java】 环境变量如何配置?
Java知识简介与环境变量配置问题 一.在学习一门语言中,不仅需要掌握其语法结构,开发平台以及环境也是很重要的.在开始Java学习之前首先对其进行压缩包的下载安装,以及开发平台环境下载安装.基于此下面 ...
- IEE重建表完全释放磁盘空间具体步骤参考
环境:RHEL 5.3 + IEE 5.1.40 本文目的:指导项目侧人员再遇到此类改动需求时可以自己更改.需求:mr_intrainterfreq表重建,历史数据全部删掉. 1.停库: 1.1确认现 ...
- 【JUC】JDK1.8源码分析之ReentrantLock(三)
一.前言 在分析了AbstractQueuedSynchronier源码后,接着分析ReentrantLock源码,其实在AbstractQueuedSynchronizer的分析中,已经提到过Ree ...