JavaScript复习——this
this
this
在面向对象编程中十分常见。JavaScript
中的 this
与 Java
中的 this
有所不同,Java
中的 this
依赖于函数的声明,而在 JavaScript
中 this
则依赖于函数的执行,因此 JavaScript
中的 this
常被称为调用上下文。
看下面代码,问函数里面的 this
等于什么?
function jikezhuan () {
console.log(this);
}
这里的 this
现在并不等于 window
,因为它可能等于包括 window
在内的许多值。如开头所述,this 依赖于函数的执行,目前函数并未执行 this
的值是未知的。
那么,接下来看看它有哪几种执行方式:
// 作为函数进行调用
function jikezhuan () {
console.log( this );
}
jikezhuan();
jikezhuan1 = jikezhuan;
jikezhuan1();
两次输出都是 Window
对象。因为这两函数在执行时,其上下文是全局。
.
// 作为方法进行调用
var jike = {name: "jikezhuan"};
jike.skill = function () {
console.log(this.name);
}
jike.skill(); // jikezhuan
通过 jike
对象的 skill
属性来调用函数,此时是作为 jike
的一个方法来调用的,该函数的上下文是 jike
, 即 this
指向 jike
对象。
.
//作为构造器进行调用
function Jike() {
this.skill = function() { return this };
}
var jike1 = new Jike();
var jike2 = new Jike();
if (jike1.skill() === jike1) {
console.log("this指向jike1");
}
if (jike2.skill() === jike2) {
console.log("this指向jike2");
}
执行以上代码,在控制台会输出 this指向jike1
, this指向jike2
。 构造器 Jike
在函数的上下文对象上创建了一个 skill
属性,该属性方法又返回了上下文自身。 在使用 new
关键字进行调用时,会创建一个空对象实例,并把该对象作为 this
参数传递给 new
后面的函数—— jike2
。
.
apply() 、call()
函数调用方式之间的主要差异是:作为 this 参数传递给执行函数的上下文对象之间的区别。作为方法进行调用,上下文是该方法的拥有者;作为全局函数进行调用,其上下文是 window(也即该函数是 window 的一个方法);作为构造函数进行调用,其上下文对象是新创建的对象实例。当一个事件处理程序被调用时,该函数的上下文将被设置为绑定事件的对象。
有时会出现这样的需求,需要自由地指定函数的上下文,而 apply() 、call() 方法就能实现这样的功能。Javascript 的每个函数都有 apply() 和 call() 方法。
apply() 方法接收两个参数,一个是作为函数上下文的对象,另一个是作为函数参数所组成的数组。call() 方法使用方式的不同点在于,给函数传入的参数是一个参数列表,而不是单个数组。
//定义一个求和函数
function sum() {
var result = 0;
for (var i = 0; i < arguments.length; i++) { //arguments参数数组
result += arguments[i];
}
this.result = result;
}
//创建两个测试对象
var test1 = {},
test2 = {};
//使用apply()、call()方法调用函数
sum.apply(test1, [1,2,3,4]);
sum.call(test2, 5, 6, 7);
console.log("test1.result", test1.result); //10
console.log("test2.result", test2.result); //18
arguments 对象
arguments 保存着函数的参数。
arguments 是一个对应于传递给函数的参数的类数组对象。它类似于
Array
,但除了length属性和索引元素之外没有任何Array
属性。arguments
对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments
对象在函数中引用函数的参数。
// 求和函数
function add () {
let sum = 0
for (let i = 0; i < arguments.length; i++) {
sum = sum + arguments[i]
}
return sum
}
add(1,2,3,4,5)
arguments.callee
arguments 对象上有一个名为 callee 的属性,其属性值为正在被执行的函数。先看一个例子,就知道 arguments.callee 的应用场景了。
现需用递归求1到n的和:
// 递归求和
// 求1~100的和
function sum (n) {
if (n > 1) {
return n + sum(n-1)
} else {
return 1
}
}
sum(100)
增加难度,用匿名函数递归求1到n的和:
// 匿名函数 递归求和
// 求1~100的和
(function (n) {
if (n > 1) {
return n + arguments.callee(n-1)
} else {
return 1
}
}) (100)