Skip to content

Function

[TOC]

索引

属性

  • function.namestring只读,返回函数定义时的名称,推断规则因定义方式而异。。适用于调试、反射(获取函数名)等场景。
  • function.lengthnumber,表示函数声明时定义的形参数量。它不会将默认参数之后的参数剩余参数计算在内。
  • function.arguments类数组对象已废弃,用于在函数内部访问函数执行时传入的参数列表,它是一个类数组对象
  • function.prototypeobject,是所有函数对象的原型对象。它定义了函数实例继承的默认属性和方法。

方法

  • function.call()(thisArg,arg1?,arg2?,...),用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。
  • function.apply()(thisArg,args?),用于显式调用一个函数,并动态指定函数执行时的 this 值及参数列表。
  • function.bind()(thisArg,arg1?,arg2?,...),用于创建一个新的函数,该函数在调用时会以指定的 this 值和预先提供的参数作为默认参数。
  • function.toString()(),用于获取函数源代码字符串表示的方法。它返回函数的完整定义,包括参数、函数体和语法结构。

Function

属性

name

function.namestring只读,返回函数定义时的名称,推断规则因定义方式而异。。适用于调试、反射(获取函数名)等场景。

不同函数类型的name值

  1. 函数声明

    显式命名:直接返回定义的名称。

    js
    function sum(a, b) { return a + b; }
    console.log(sum.name); // "sum"
  2. 匿名函数表达式

    ES5 及之前:匿名函数的 name 为空字符串 ""

    ES6 及之后:若函数被赋值给变量,name 会推断为变量名。

    js
    const multiply = function(a, b) { return a * b; };
    console.log(multiply.name); // "multiply"(ES6+)
    
    const func = function() {};
    console.log(func.name); // "func"
  3. 箭头函数

    行为与函数表达式一致,name 推断为变量名。

    js
    const divide = (a, b) => a / b;
    console.log(divide.name); // "divide"
  4. 构造函数(类)

    返回类名,与函数声明行为一致。

    js
    class Person {
      constructor(name) { this.name = name; }
    }
    console.log(Person.name); // "Person"
    
    const Car = function() {};
    console.log(Car.name); // "Car"
  5. 对象方法

    普通方法:返回方法名。

    js
    const obj = {
      sayHello() { console.log("Hello"); }
    };
    console.log(obj.sayHello.name); // "sayHello"

    计算属性名:返回实际定义的方法名。

    js
    const methodName = 'dynamicMethod';
    const obj2 = {
      [methodName]() {}
    };
    console.log(obj2[methodName].name); // "dynamicMethod"

    Symbol属性名:返回 Symbol 的描述(需通过 toString() 获取完整信息)。

    js
    const sym = Symbol('customSymbol')
    const obj = {
      [sym]: function () {
        console.log(obj[sym].name) // [customSymbol]
      }
    }
    obj[sym]()
  6. 动态创建的函数

    通过 new Function():返回 "anonymous"

    js
    const dynamicFunc = new Function('a', 'b', 'return a + b');
    console.log(dynamicFunc.name); // "anonymous"

    通过 bind():返回原函数名前缀加 "bound "

    js
    function greet() {}
    const boundGreet = greet.bind({});
    console.log(boundGreet.name); // "bound greet"
  7. Getter/Setter 方法

    返回 getset 前缀的属性名

    js
    const obj3 = {
      get value() { return this._value; },
      set value(v) { this._value = v; }
    };
    console.log(obj3.value.getter?.name); // "get value"(需通过对象描述符获取)
  8. 默认参数函数

    返回函数本身的名称。

    js
    function defaultFunc(param = function() {}) {
        console.log(param.name); // "param"(非标准行为,因环境而异)
    }
    defaultFunc();

应用场景

  1. 遍历区分存储在数组中的函数

    image-20250509173746517

length

function.lengthnumber,表示函数声明时定义的形参数量。它不会将默认参数之后的参数剩余参数计算在内。

语法特性

  1. 基本定义

    返回函数声明时定义的形参数量,不包含默认参数之后的参数和剩余参数。

    js
    function sum(a, b, c) {} // 3
  2. 默认参数的影响

    length 计算到第一个具有默认值的参数之前,后续参数无论是否有默认值均不计数。

    js
    function func1(a, b = 0, c) {} // 1(a 无默认值,b 有默认值,之后参数不计)
    
    function func2(a = 0, b, c) {} // 0(第一个参数 a 有默认值)
  3. 剩余参数(Rest Parameters)

    剩余参数不计入 length,但会计算其之前的参数。

    js
    function rest1(...args) {} // 0
    
    function rest2(a, ...args) {} // 1(a 计入,...args 不计)
  4. 解构赋值参数

    解构参数视为一个整体参数,不影响计数规则。

    js
    function destructure1({ x, y }, z) {} // 2(两个参数:对象解构和 z)
    
    function destructure2([a, b] = [], c) {} // 0(第一个参数有默认值)

arguments

function.arguments类数组对象已废弃,用于在函数内部访问函数执行时传入的参数列表,它是一个类数组对象

历史行为

非严格模式:允许通过函数名.arguments此属性获取参数。

js
function fn(a, b) {
  console.log(fn.arguments); // Arguments(2) [1, 2, callee: ƒ, Symbol(Symbol.iterator): ƒ]
}
fn(1, 2);

严格模式:在函数内部直接通过 arguments 访问参数(非箭头函数)。

js
function sum(a, b) {
  console.log(arguments[0], arguments[1]); // 1, 2
  return a + b;
}
sum(1, 2);

转数组类型:通过 Array.from(arguments)[...arguments ] 将类数组的 arguments 转为数组。

js
function convertToArray() {
  const argsArray = Array.from(arguments);
  // 或 const argsArray = [...arguments];
  console.log(argsArray); // [1, 2, 3]
}
convertToArray(1, 2, 3);

箭头函数不绑定 arguments

箭头函数是不绑定 arguments 的,所以我们在箭头函数中使用 arguments 会去上层作用域查找:

  • 箭头函数不绑定 arguments

    js
    const bar = (x, y, z) => {
      console.log(arguments) // Uncaught ReferenceError: arguments is not defined
    }
    bar(10, 20, 30)
  • 在箭头函数中使用 arguments 会去上层作用域查找

    js
    const 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 对象,也无法通过此方式访问参数:

    js
    const arrowFunc = () => {
      console.log(arrowFunc.arguments); // 报错或无输出
    };
    arrowFunc(1, 2);

prototype

function.prototypeobject,是所有函数对象的原型对象。它定义了函数实例继承的默认属性和方法。

  • 语法:

    1. 本质:Function.prototype 是一个内置的函数对象

    2. 原型链

      所有函数(包括 Function 构造函数自身) → Function.prototypeObject.prototypenull

    3. 直接调用:虽然 Function.prototype 是函数,但直接调用它没有实际效果:

      js
      Function.prototype(); // 无操作,返回 undefined****:
  • 属性/方法:

    由于 Function.prototype 本质上是一个函数对象,所以它也具有 Function 的属性和方法(如name,length等)。

  • 特性:

    1. 箭头函数的限制:箭头函数继承自 Function.prototype,但无法通过 call()/apply() 修改 this:

      js
      const arrow = () => console.log(this);
      arrow.call({ value: 42 }); // 输出全局对象(如 window)
  • 示例:

    1. 扩展函数功能

      通过修改 Function.prototype(不推荐,可能引发冲突):

      js
      Function.prototype.log = function(...args) {
        console.log("调用函数:", this.name);
        return this(...args);
      };
      function sum(a, b) { return a + b; }
      sum.log(2, 3); // 输出 "调用函数: sum" 并返回 5
    2. 实现高阶函数

      利用 bind() 预设参数:

      js
      const multiply = (a, b) => a * b;
      const double = multiply.bind(null, 2);
      console.log(double(5)); // 10
    3. 动态调用方法

      借用其他对象的方法:

      js
      const 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 值及参数列表。

  • thisArgany,调用函数时绑定的 this 值。

  • arg1?,arg2?,...any,按顺序传递给函数的参数列表,与函数定义时的形参一一对应

  • 返回:

  • resultany|undefined,返回函数的执行结果。若函数无返回值,则返回 undefined。

  • 特性:

    1. 动态绑定 this

      js
      const obj1 = { value: 10 };
      const obj2 = { value: 20 };
      
      function getValue() {
        return this.value;
      }
      
      console.log(getValue.call(obj1)); // 10
      console.log(getValue.call(obj2)); // 20
    2. 参数按顺序传递

      js
      function sum(a, b, c) {
        return a + b + c; // 1 + 2 + 3
      }
      
      console.log(sum.call(null, 1, 2, 3)); // 6
    3. 借用其他对象的方法

      js
      // 类数组对象借用数组方法
      const arrayLike = { 0: "a", 1: "b", length: 2 };
      console.log(Array.prototype.join.call(arrayLike, "-")); // "a-b"
    4. 箭头函数不绑定 this:箭头函数没有自己的 this,call() 的 thisArg 对其无效

      js
      const arrowFunc = () => console.log(this);
      arrowFunc.call({ value: 42 }); // 输出全局对象(如 window)
    5. 严格模式:严格模式下,thisArg 不会被隐式转换为全局对象 winodw:

      js
      'use strict';
      function logThis() {
        console.log(this);	
      }
      logThis.call(null); // 输出 null
  • 应用场景:

    1. 调用父类构造函数(继承)

      js
      function 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}
    2. 处理可变参数

      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 值及参数列表。

  • thisArgany,调用函数时绑定的 this 值。

  • args?any[],函数调用时传递的参数列表,以数组或类数组形式存在

  • 返回:

  • resultany|undefined,返回函数的执行结果。如果函数没有返回值,则返回 undefined。

  • 特性:

    1. call() 类似

    2. 对比 call():性能差异可忽略(现代引擎已优化)。

      • call():参数逐个传递。
      • apply():参数以数组形式传递。
      js
      function 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 值和预先提供的参数作为默认参数。

  • thisArgany,调用绑定函数时,原函数内部的 this 值。

  • arg1?,arg2?,...any,预先传递给原函数的参数,会插入到新函数调用时的参数列表前。

  • 返回:

  • boundFunctionFunction,返回一个新的函数,其行为如下:

    • this 被固定为 thisArg。

    • 调用 boundFunction 时,参数为 预先绑定的参数 + 新传入的参数

    • 如果原函数通过 new 调用,thisArg 会被忽略(构造函数行为)。

  • 特性:

    1. call() 类似
    2. 对比 call 和 apply
    • bind()不会立即执行绑定函数function,而是返回一个新的函数。

toString()

function.toString()(),用于获取函数源代码字符串表示的方法。它返回函数的完整定义,包括参数、函数体和语法结构。

  • 返回:

  • fnStringstring,一个表示函数源代码的字符串。

  • 特性:

    1. 基本行为

      • 用户定义的函数:返回其完整的定义字符串,包括 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] }"
    2. 不同函数类型的输出

      • 箭头函数:保留箭头语法。

        js
        const arrow = (x, y) => x + y;
        console.log(arrow.toString()); // "(x, y) => x + y"
      • 生成器函数:保留 function* 语法。

        js
        function* gen() { yield 1; }
        console.log(gen.toString()); // "function* gen() { yield 1; }"
      • 异步函数:保留 async 关键字。

        js
        async function fetchData() { /* ... */ }
        console.log(fetchData.toString()); // "async function fetchData() { /* ... */ }"
      • 绑定函数(bind() 创建):可能显示 bound 前缀。

        js
        function greet() { return this.name; }
        const boundGreet = greet.bind({ name: "Alice" });
        console.log(boundGreet.toString()); // "function () { [native code] }" 或 "function bound greet() { ... }"(因环境而异)
      • 动态创建的函数:通过 new Function() 创建的函数,返回其定义字符串。

        js
        const dynamicFunc = new Function('a', 'b', 'return a + b');
        console.log(dynamicFunc.toString()); // 输出: "function anonymous(a, b) { return a + b }"
  • 注意:

    1. 格式与注释是否保留:不同 JS 引擎可能在输出的字符串中保留或移除注释和空格。

      js
      function commented() { /* 注释 */ }
      console.log(commented.toString()); // 可能包含注释,也可能不包含(依环境而定)