文章目录
Function
Function
是 JavaScript 中的一个内置对象,用于表示函数或方法。每一个函数都是 Function
类型的实例。你可以使用 Function
构造函数来创建新的函数,尽管这种方式不如使用函数声明或函数表达式常见。
1. Function
构造函数
Function
构造函数允许你动态地创建函数。它的语法如下:
new Function ([arg1[, arg2[, ...argN]],] functionBody)
arg1, arg2, ... argN
:函数的参数,这些参数是字符串形式的。functionBody
:函数的主体,也是一个字符串。
例如:
var add = new Function('a', 'b', 'return a + b');
console.log(add(1, 2)); // 输出 3
尽管 Function
构造函数可以实现动态函数创建,但这种方式通常不推荐,因为它可能导致代码难以理解和维护,并且可能增加性能开销。
2. Function
类型的属性和方法
Function
类型有一些属性和方法,用于获取或操作函数。
属性:
length
:返回函数期望的参数个数,不包括rest
参数。
方法:
call()
:调用一个具有给定this
值和作为一个数组(或类似数组对象)提供的参数的函数。apply()
:调用一个具有给定this
值和以一个数组(或类似数组对象)的形式提供的参数的函数。bind()
:创建一个新的函数,在bind()
被调用时,这个新函数的this
被指定为bind()
的第一个参数,其余的参数将作为新函数的参数供调用时使用。
3. 函数声明和函数表达式
除了使用 Function
构造函数,我们更常使用函数声明和函数表达式来创建函数。
函数声明:
function myFunction(a, b) {
return a + b;
}
函数表达式:
var myFunction = function(a, b) {
return a + b;
};
这两种方式比使用 Function
构造函数更常见,因为它们提供了更好的可读性和性能。
4. 闭包和函数作用域
在 JavaScript 中,函数可以访问和操作其外部词法环境(lexical environment)的变量,这种特性被称为闭包(closure)。闭包是 JavaScript 中一个强大的概念,它允许我们创建可以在其外部环境中保留和操作数据的函数。
总结
Function
在 JavaScript 中是一个基础且重要的对象,它用于表示函数。尽管我们可以使用 Function
构造函数来创建函数,但更常见和推荐的方式是使用函数声明和函数表达式。此外,了解闭包和函数作用域对于深入理解 JavaScript 中的函数非常关键。
每个 JavaScript 函数实际上都是一个 Function 对象。运行 (function(){}).constructor === Function // true 便可以得到这个结论。
实例属性
arguments
是一个对应于传递给函数的参数的类数组对象。
function func1(a, b, c) {
console.log(arguments[0]);
// expected output: 1
console.log(arguments[1]);
// expected output: 2
console.log(arguments[2]);
// expected output: 3
}
func1(1, 2, 3);
Function.length
length 属性指明函数的形参个数。
function func1() {}
function func2(a, b) {}
console.log(func1.length);
// expected output: 0
console.log(func2.length);
// expected output: 2
实例方法
Function.length
length 属性指明函数的形参个数。
function func1() {}
function func2(a, b) {}
console.log(func1.length);
// expected output: 0
console.log(func2.length);
// expected output: 2
apply()的语法
call 与 apply 用于显示的设置函数的上下文,两个方法作用一样都是将对象绑定到 this,只是在传递参数上有所不同。
call 和 apply 都是为了解决改变 this 的指向。作用都是相同的,只是传参的方式不同。
call 可以接收一个参数列表
apply 只接受一个参数数组。
与 bind 不同 call/apply 会立即执行函数
function show(title) {
console.log(`${title + this.name}`);
}
let lisi = {
name: "李四",
};
let wangwu = {
name: "王五",
};
show.call(lisi, "用户1:");
show.apply(wangwu, ["用户2:"]);
// 用户1:李四
// 用户2:王五
Function.prototype.bind()
bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
const module = {
x: 42,
getX: function () {
return this.x;
},
};
const unboundGetX = module.getX;
console.log(unboundGetX()); // The function gets invoked at the global scope
// expected output: undefined
const boundGetX = unboundGetX.bind(module);
console.log(boundGetX());
// expected output: 42
Function.prototype.toString()
toString() 方法返回一个表示当前函数源代码的字符串。
function sum(a, b) {
return a + b;
}
console.log(sum.toString());
// expected output: "function sum(a, b) {
// return a + b;
// }"
console.log(Math.abs.toString());
// expected output: "function abs() { [native code] }"
Function.prototype.call()
语法
function.call(thisArg, arg1, arg2, …)
call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
返回值
- 使用调用者提供的 this 值和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = "food";
}
console.log(new Food("cheese", 5).name);
// expected output: "cheese"
var animals = [
{ species: 'Lion', name: 'King' },
{ species: 'Whale', name: 'Fail' }
];
for (var i = 0; i < animals.length; i++) {
(function(i) {
this.print = function() {
console.log('#' + i + ' ' + this.species
+ ': ' + this.name);
}
this.print();
}).call(animals[i], i);
}
//#0 Lion: King
// #1 Whale: Fail
使用 call 方法调用函数并且指定上下文的 ‘this’
在下面的例子中,当调用 greet 方法的时候,该方法的this值会绑定到 obj 对象。
function greet() {
var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
var obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
Function.prototype.apply()
- 语法
apply(thisArg)
apply(thisArg, argsArray)
-
thisArg:在 fun 函数运行时指定的 this 值。需要注意的是,指定的 this 值并不一定是该函数执行时真正的 this 值,如果这个函数处于非严格模式下,则指定为 null 或 undefined 时会自动指向全局对象(浏览器中就是window对象),同时值为原始值(数字,字符串,布尔值)的 this 会指向该原始值的自动包装对象。
-
argsArray:一个数组或者类数组对象,其中的数组元素将作为单独的参数传给 fun 函数。如果该参数的值为null 或 undefined,则表示不需要传入任何参数。从ECMAScript 5 开始可以使用类数组对象。浏览器兼容性请参阅本文底部内容。
返回值
调用有指定 this 值和参数的函数的结果。
const numbers = [5, 6, 2, 3, 7];
const max = Math.max.apply(null, numbers);
console.log(max);
// expected output: 7
const min = Math.min.apply(null, numbers);
console.log(min);
// expected output: 2
apply 和 call 的区别
-
其实 apply 和 call 基本类似,他们的区别只是传入的参数不同。
-
所以 apply 和 call 的区别是 call 方法接受的是若干个参数列表,而 apply 接收的是一个包含多个参数的数组。
Function.prototype.bind()
- bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
语法
function.bind(thisArg[, arg1[, arg2[, …]]])
参数
thisArg
- 调用绑定函数时作为 this 参数传递给目标函数的值。如果使用new运算符构造绑定函数,则忽略该值。当使用 bind 在 setTimeout 中创建一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者thisArg是null或undefined,执行作用域的 this 将被视为新函数的 thisArg。
arg1, arg2, ...
- 当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
返回值
- 返回一个原函数的拷贝,并拥有指定的 this 值和初始参数。
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.bind(a,1,2)
所以我们可以看出,bind 是创建一个新的函数,我们必须要手动去调用:
var a ={
name : "Cherry",
fn : function (a,b) {
console.log( a + b)
}
}
var b = a.fn;
b.bind(a,1,2)() // 3