Function
[TOC]
索引
属性:
- function.name:
string
,只读,返回函数定义时的名称,推断规则因定义方式而异。。适用于调试、反射(获取函数名)等场景。 - function.length:
number
,表示函数声明时定义的形参数量。它不会将默认参数之后的参数、剩余参数计算在内。 - function.arguments:
类数组对象
,已废弃,用于在函数内部访问函数执行时传入的参数列表,它是一个类数组对象。 - function.prototype:
object
,是所有函数对象的原型对象。它定义了函数实例继承的默认属性和方法。
方法:
- function.call():
(thisArg,arg1?,arg2?,...)
,用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。 - function.apply():
(thisArg,args?)
,用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。 - function.bind():
(thisArg,arg1?,arg2?,...)
,用于创建一个新的函数,该函数在调用时会以指定的 this 值和预先提供的参数作为默认参数。 - function.toString():
()
,用于获取函数源代码字符串表示的方法。它返回函数的完整定义,包括参数、函数体和语法结构。
Function
属性
name
function.name:string
,只读,返回函数定义时的名称,推断规则因定义方式而异。。适用于调试、反射(获取函数名)等场景。
不同函数类型的name值:
函数声明
显式命名:直接返回定义的名称。
jsfunction sum(a, b) { return a + b; } console.log(sum.name); // "sum"
匿名函数表达式
ES5 及之前:匿名函数的
name
为空字符串""
。ES6 及之后:若函数被赋值给变量,
name
会推断为变量名。jsconst multiply = function(a, b) { return a * b; }; console.log(multiply.name); // "multiply"(ES6+) const func = function() {}; console.log(func.name); // "func"
箭头函数
行为与函数表达式一致,
name
推断为变量名。jsconst divide = (a, b) => a / b; console.log(divide.name); // "divide"
构造函数(类)
返回类名,与函数声明行为一致。
jsclass Person { constructor(name) { this.name = name; } } console.log(Person.name); // "Person" const Car = function() {}; console.log(Car.name); // "Car"
对象方法
普通方法:返回方法名。
jsconst obj = { sayHello() { console.log("Hello"); } }; console.log(obj.sayHello.name); // "sayHello"
计算属性名:返回实际定义的方法名。
jsconst methodName = 'dynamicMethod'; const obj2 = { [methodName]() {} }; console.log(obj2[methodName].name); // "dynamicMethod"
Symbol属性名:返回
Symbol
的描述(需通过toString()
获取完整信息)。jsconst sym = Symbol('customSymbol') const obj = { [sym]: function () { console.log(obj[sym].name) // [customSymbol] } } obj[sym]()
动态创建的函数
通过
new Function()
:返回 "anonymous"。jsconst dynamicFunc = new Function('a', 'b', 'return a + b'); console.log(dynamicFunc.name); // "anonymous"
通过
bind()
:返回原函数名前缀加 "bound "。jsfunction greet() {} const boundGreet = greet.bind({}); console.log(boundGreet.name); // "bound greet"
Getter/Setter 方法
返回
get
或set
前缀的属性名。jsconst obj3 = { get value() { return this._value; }, set value(v) { this._value = v; } }; console.log(obj3.value.getter?.name); // "get value"(需通过对象描述符获取)
默认参数函数
返回函数本身的名称。
jsfunction defaultFunc(param = function() {}) { console.log(param.name); // "param"(非标准行为,因环境而异) } defaultFunc();
应用场景:
遍历区分存储在数组中的函数
length
function.length:number
,表示函数声明时定义的形参数量。它不会将默认参数之后的参数、剩余参数计算在内。
语法特性:
基本定义
返回函数声明时定义的形参数量,不包含默认参数之后的参数和剩余参数。
jsfunction sum(a, b, c) {} // 3
默认参数的影响
length
计算到第一个具有默认值的参数之前,后续参数无论是否有默认值均不计数。jsfunction func1(a, b = 0, c) {} // 1(a 无默认值,b 有默认值,之后参数不计) function func2(a = 0, b, c) {} // 0(第一个参数 a 有默认值)
剩余参数(Rest Parameters)
剩余参数不计入
length
,但会计算其之前的参数。jsfunction rest1(...args) {} // 0 function rest2(a, ...args) {} // 1(a 计入,...args 不计)
解构赋值参数
解构参数视为一个整体参数,不影响计数规则。
jsfunction destructure1({ x, y }, z) {} // 2(两个参数:对象解构和 z) function destructure2([a, b] = [], c) {} // 0(第一个参数有默认值)
arguments
function.arguments:类数组对象
,已废弃,用于在函数内部访问函数执行时传入的参数列表,它是一个类数组对象。
历史行为:
非严格模式:允许通过函数名.arguments
此属性获取参数。
function fn(a, b) {
console.log(fn.arguments); // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
}
fn(1, 2);
严格模式:在函数内部直接通过 arguments
访问参数(非箭头函数)。
function sum(a, b) {
console.log(arguments[0], arguments[1]); // 1, 2
return a + b;
}
sum(1, 2);
转数组类型:通过 Array.from(arguments)
或[...arguments ]
将类数组的 arguments 转为数组。
function convertToArray() {
const argsArray = Array.from(arguments);
// 或 const argsArray = [...arguments];
console.log(argsArray); // [1, 2, 3]
}
convertToArray(1, 2, 3);
箭头函数不绑定 arguments:
箭头函数是不绑定 arguments 的,所以我们在箭头函数中使用 arguments 会去上层作用域查找:
箭头函数不绑定 arguments
jsconst bar = (x, y, z) => { console.log(arguments) // Uncaught ReferenceError: arguments is not defined } bar(10, 20, 30)
在箭头函数中使用 arguments 会去上层作用域查找
jsconst bar = function (m, n) { return (x, y, z) => { console.log(arguments) // Arguments(2) [10, 20, callee: ƒ, Symbol(Symbol.iterator): ƒ] } } const fn = bar(10, 20) fn('a', 'b', 'c')
废弃原因:
严格模式报错
在严格模式(
'use strict'
)下,访问function.arguments
会直接抛出错误:js'use strict'; function func() { console.log(func.arguments); // TypeError: 'caller', 'callee', and 'arguments' may not be accessed } func();
性能与安全性问题
- 引擎难以优化此属性的访问。
- 暴露函数执行上下文的细节,可能引发安全问题。
箭头函数的限制
箭头函数没有自己的
arguments
对象,也无法通过此方式访问参数:jsconst arrowFunc = () => { console.log(arrowFunc.arguments); // 报错或无输出 }; arrowFunc(1, 2);
prototype
function.prototype:object
,是所有函数对象的原型对象。它定义了函数实例继承的默认属性和方法。
语法:
本质:Function.prototype 是一个内置的函数对象。
原型链:
所有函数(包括
Function
构造函数自身) →Function.prototype
→Object.prototype
→null
。直接调用:虽然
Function.prototype
是函数,但直接调用它没有实际效果:jsFunction.prototype(); // 无操作,返回 undefined****:
属性/方法:
由于 Function.prototype 本质上是一个函数对象,所以它也具有 Function 的属性和方法(如name,length等)。
特性:
箭头函数的限制:箭头函数继承自 Function.prototype,但无法通过 call()/apply() 修改 this:
jsconst arrow = () => console.log(this); arrow.call({ value: 42 }); // 输出全局对象(如 window)
示例:
扩展函数功能
通过修改
Function.prototype
(不推荐,可能引发冲突):jsFunction.prototype.log = function(...args) { console.log("调用函数:", this.name); return this(...args); }; function sum(a, b) { return a + b; } sum.log(2, 3); // 输出 "调用函数: sum" 并返回 5
实现高阶函数
利用
bind()
预设参数:jsconst multiply = (a, b) => a * b; const double = multiply.bind(null, 2); console.log(double(5)); // 10
动态调用方法
借用其他对象的方法:
jsconst arrayLike = { 0: "a", 1: "b", length: 2 }; const arr = Array.prototype.slice.call(arrayLike); console.log(arr); // ["a", "b"]
方法
call()
function.call():(thisArg,arg1?,arg2?,...)
,用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。
thisArg:
any
,调用函数时绑定的 this 值。arg1?,arg2?,...:
any
,按顺序传递给函数的参数列表,与函数定义时的形参一一对应。返回:
result:
any|undefined
,返回函数的执行结果。若函数无返回值,则返回 undefined。特性:
动态绑定 this:
jsconst obj1 = { value: 10 }; const obj2 = { value: 20 }; function getValue() { return this.value; } console.log(getValue.call(obj1)); // 10 console.log(getValue.call(obj2)); // 20
参数按顺序传递:
jsfunction sum(a, b, c) { return a + b + c; // 1 + 2 + 3 } console.log(sum.call(null, 1, 2, 3)); // 6
借用其他对象的方法:
js// 类数组对象借用数组方法 const arrayLike = { 0: "a", 1: "b", length: 2 }; console.log(Array.prototype.join.call(arrayLike, "-")); // "a-b"
箭头函数不绑定 this:箭头函数没有自己的 this,call() 的 thisArg 对其无效
jsconst arrowFunc = () => console.log(this); arrowFunc.call({ value: 42 }); // 输出全局对象(如 window)
严格模式:严格模式下,thisArg 不会被隐式转换为全局对象 winodw:
js'use strict'; function logThis() { console.log(this); } logThis.call(null); // 输出 null
应用场景:
调用父类构造函数(继承)
jsfunction Parent(name) { this.name = name; } function Child(name, age) { Parent.call(this, name); // 调用父类构造函数 this.age = age; } const child = new Child("Alice", 10); console.log(child); // Child {name: "Alice", age: 10}
处理可变参数
js// 借用 Math.max 找最大值 const numbers = [5, 3, 8, 1]; console.log(Math.max.call(null, ...numbers)); // 8 可以这样调用:Math.max(...numbers)
apply()
function.apply():(thisArg,args?)
,用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。
thisArg:
any
,调用函数时绑定的 this 值。args?:
any[]
,函数调用时传递的参数列表,以数组或类数组形式存在。返回:
result:
any|undefined
,返回函数的执行结果。如果函数没有返回值,则返回 undefined。特性:
与 call() 类似:
对比 call():性能差异可忽略(现代引擎已优化)。
call()
:参数逐个传递。apply()
:参数以数组形式传递。
jsfunction sum(a, b, c) { return a + b + c; // 1 + 2 + 3 } // call console.log(sum.call(null, 1, 2, 3)); // 6 // apply console.log(sum.apply(null, [1, 2, 3])); //
bind()
function.bind():(thisArg,arg1?,arg2?,...)
,用于创建一个新的函数,该函数在调用时会以指定的 this 值和预先提供的参数作为默认参数。
thisArg:
any
,调用绑定函数时,原函数内部的 this 值。arg1?,arg2?,...:
any
,预先传递给原函数的参数,会插入到新函数调用时的参数列表前。返回:
boundFunction:
Function
,返回一个新的函数,其行为如下:this 被固定为 thisArg。
调用 boundFunction 时,参数为 预先绑定的参数 + 新传入的参数。
如果原函数通过 new 调用,thisArg 会被忽略(构造函数行为)。
特性:
- 与 call() 类似:
- 对比 call 和 apply:
- bind()不会立即执行绑定函数function,而是返回一个新的函数。
toString()
function.toString():()
,用于获取函数源代码字符串表示的方法。它返回函数的完整定义,包括参数、函数体和语法结构。
返回:
fnString:
string
,一个表示函数源代码的字符串。特性:
基本行为:
- 用户定义的函数:返回其完整的定义字符串,包括
function
关键字、函数名、参数列表和函数体。 - 内置函数或原生代码实现的函数:返回的字符串通常包含
[native code]
,表示源代码不可访问。
js// 1. 用户定义的函数 function add(a, b) { return a + b; } console.log(add.toString()); // 输出: "function add(a, b) { return a + b; }" // 2. 内置函数或原生代码实现的函数 console.log(Math.max.toString()); // 输出: "function max() { [native code] }"
- 用户定义的函数:返回其完整的定义字符串,包括
不同函数类型的输出:
箭头函数:保留箭头语法。
jsconst arrow = (x, y) => x + y; console.log(arrow.toString()); // "(x, y) => x + y"
生成器函数:保留
function*
语法。jsfunction* gen() { yield 1; } console.log(gen.toString()); // "function* gen() { yield 1; }"
异步函数:保留
async
关键字。jsasync function fetchData() { /* ... */ } console.log(fetchData.toString()); // "async function fetchData() { /* ... */ }"
绑定函数(
bind()
创建):可能显示bound
前缀。jsfunction greet() { return this.name; } const boundGreet = greet.bind({ name: "Alice" }); console.log(boundGreet.toString()); // "function () { [native code] }" 或 "function bound greet() { ... }"(因环境而异)
动态创建的函数:通过
new Function()
创建的函数,返回其定义字符串。jsconst dynamicFunc = new Function('a', 'b', 'return a + b'); console.log(dynamicFunc.toString()); // 输出: "function anonymous(a, b) { return a + b }"
注意:
格式与注释是否保留:不同 JS 引擎可能在输出的字符串中保留或移除注释和空格。
jsfunction commented() { /* 注释 */ } console.log(commented.toString()); // 可能包含注释,也可能不包含(依环境而定)