JS 内置对象之 Function
一、属性
1、length
指该函数有多少个必须要传入的参数,即形参的个数。
function func1() { }
function func2(a, b) { }
console.log(func1.length); // 0
console.log(func2.length); // 2
2、name
返回函数实例的名称。
2-1、函数声明的名称
函数声明的名称及函数名。
function doSomething() { }
doSomething.name; // "doSomething"
2-2、构造函数的名称
使用 new Function(...) 创建的函数其名称为 “anonymous”。
(new Function).name; // "anonymous"
2-3、绑定函数的名称
Function.bind() 创建的函数将会在其函数名称前加上 "bound "。
function foo() { };
foo.bind({}).name; // "bound foo"
2-4、getters 和 setters 的函数名
当通过 get
和 set
访问器来存取属性时, get
或 set
会出现在函数名称前。
var o = {
get foo() { },
set foo(x) { }
};
var descriptor = Object.getOwnPropertyDescriptor(o, "foo");
descriptor.get.name; // "get foo"
descriptor.set.name; // "set foo";
二、方法
1、call
function.call(thisArg, arg1, arg2, ...)
功能:提供新的 this
值给当前调用的函数/方法。
参数:
- thisArg(可选):在 function 函数运行时使用的
this
值。 - arg1, arg2, ...:指定的参数列表。
返回值:用所提供的 this
和参数调用该函数的返回值。若该方法没有返回值,则返回 undefined。
示例:
window.name = 'Tim';
const obj1 = {
name: 'Duke'
};
const obj2 = {
name: 'Bang'
};
const getName = function () {
console.log(this.name);
};
getName(); // Tim
getName.call(obj1); // Duke
getName.call(obj2); // Bang
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况;
- 判断传入上下文对象是否存在,如果不存在,则设置为 window;
- 处理传入的参数,截取第一个参数后的所有参数;
- 将函数作为上下文对象的一个属性;
- 使用上下文对象来调用这个方法,并保存返回结果;
- 删除刚才新增的属性;
- 返回结果。
// call 函数实现
Function.prototype.myCall = function (context) {
// 判断调用对象
if (typeof this !== "function") {
console.error("type error");
}
// 获取参数
let args = [...arguments].slice(1),
result = null;
// 判断 context 是否传入,如果未传入则设置为 window
context = context || window;
// 将调用函数设为对象的方法
context.fn = this;
// 调用函数
result = context.fn(...args);
// 将属性删除
delete context.fn;
return result;
};
2、apply
func.apply(thisArg, [argsArray])
功能:提供新的 this
值给当前调用的函数/方法,及以一个数组(或类数组对象)的形式提供的参数。
参数:
- thisArg(必选):在 function 函数运行时使用的
this
值。 - argsArray(可选):指定的参数数组,其中数组元素作为单独的参数传给 func 函数。
返回值:调用有指定 this
值和参数的函数的结果。
与 call 的区别:call 接受的是一个参数列表,而 apply 接受的是一个包含多个参数的数组。
示例 1:
var array = ['a', 'b'];
var elements = [1, 2, 3];
array.push(elements);
console.log(array); // ['a', 'b', [1, 2, 3]]
以上代码中,整个 elements 数组被视为一个元素直接 push
进去。如果我们想要将数组 elemennts 中的元素分别 push
进数组 array,可以使用 apply()。
var array = ['a', 'b'];
var elements = [1, 2, 3];
array.push.apply(array, elements);
console.log(array); // ["a", "b", 1, 2, 3]
这里使用 apply 连接给定数组,参数为数组 elements,this
指向变量 array,实现数组 elements 中的元素被 push
进 this
指向的对象(array)中。
示例 2:
console.log(Math.max(1, 3, 2)); // 3
console.log(Math.max([1, 3, 2])); // NaN
JS 中 max 函数用于查找给定元素的最大值。如果给定值为数组,返回结果为 NaN,可以使用 apply 解决。
console.log(Math.max.apply(null, [1, 3, 2])); // 3
使用 apply 调用 Math.max() 时,得到了期望结果。apply 将 numbers 中所有值作为单独的参数,然后再调用 max 进行处理,最终返回数组中的最大值。这里使用 null 代替了 this
。由于提供的参数是数字数组,即使使用了 this
,它也仍会指向同一个数组,最终得到相同的结果。因此,这种情况下我们可以省略 this
,改用 null 代替。
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况;
- 判断传入上下文对象是否存在,如果不存在,则设置为 window;
- 将函数作为上下文对象的一个属性;
- 判断参数值是否传入;
- 使用上下文对象来调用这个方法,并保存返回结果;
- 删除刚才新增的属性;
- 返回结果。
// apply 函数实现
Function.prototype.myApply = function (context) {
// 判断调用对象是否为函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
let result = null;
// 判断 context 是否存在,如果未传入则为 window
context = context || window;
// 将函数设为对象的方法
context.fn = this;
// 调用方法
if (arguments[1]) {
result = context.fn(...arguments[1]);
} else {
result = context.fn();
}
// 将属性删除
delete context.fn;
return result;
};
3、bind
function.bind(thisArg[, arg1[, arg2[, ...]]])
功能:创建一个新的函数,在 bind() 被调用时,这个新函数的 this
被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
参数:
- thisArg(可选):调用绑定函数时传递给目标函数的
this
值。 - arg1, arg2, ...:当目标函数被调用时,被预置入绑定函数的参数列表中的参数。
返回值:返回一个原函数的拷贝,并拥有指定的 this
值和初始参数。
与 call 的区别:bind 返回一个新函数,而 call 不返回。
示例:
const name = 'Tim';
const star = {
name: 'Bang',
};
function getName () {
return this.name;
}
console.log(getName()); // Tim
console.log(getName.bind(star)); // ƒ getName () {return this.name;}
console.log(getName.bind(star)()); // Bang
- 判断调用对象是否为函数,即使我们是定义在函数的原型上的,但是可能出现使用 call 等方式调用的情况;
- 保存当前函数的引用,获取其余传入参数值;
- 创建一个函数返回;
- 函数内部使用 apply 来绑定函数调用,需要判断函数作为构造函数的情况,这个时候需要传入当前函数的 this 给 apply 调用,其余情况都传入指定的上下文对象。
// bind 函数实现
Function.prototype.myBind = function (context) {
// 判断调用对象是否为函数
if (typeof this !== "function") {
throw new TypeError("Error");
}
// 获取参数
var args = [...arguments].slice(1),
fn = this;
return function Fn() {
// 根据调用方式,传入不同绑定值
return fn.apply(
this instanceof Fn ? this : context,
args.concat(...arguments)
);
};
};
4、toString
function.toString()
功能:返回一个表示当前函数源代码的字符串。
参数:无
返回值:表示函数源代码的一个字符串。
示例:
function sum(a, b) {
return a + b;
}
console.log(sum.toString());
// 输出:
// function sum(a, b) {
// return a + b;
// }
console.log(Math.abs.toString());
// 输出:
// function abs() { [native code] }