本文面向前端面试,系统总结 JS 函数与对象的高级知识点,涵盖 arguments、柯里化、纯函数、严格模式、属性描述符等重点内容,附记忆口诀与典型面试题,助你快速突破 JS 核心考点。


一、函数对象的属性

JavaScript 函数本质上是对象,可以有属性

属性说明
name函数名称
length函数参数长度(不含 rest 参数)

记忆点:
length !== arguments.length,rest 参数不计算在 length 内


二、arguments 与 Rest 参数

1)arguments 特性

特点说明
类数组对象有 length、有索引,无 array 方法
一般用于 ES5 函数内部function fn(){} 才能获取
不推荐 ES6 及以后使用rest 参数更优雅

转 Array 方法

Array.from(arguments) [...arguments]

2)箭头函数无 arguments

箭头函数 不会创建 arguments,会向上查找作用域。

const fn = () => console.log(arguments) // ❌

3)Rest 参数 ✅ 推荐

function sum(...args){ console.log(args); }
维度argumentsrest
类型类数组真数组 ✅
箭头函数❌✅
建议程度不推荐强烈推荐 ✅

三、纯函数(React/函数式编程核心)

定义(必须同时满足)

条件含义
固定输入 → 固定输出输出只由输入决定
无副作用不修改外部变量,不产生 I/O 影响

副作用示例

✅ 纯函数❌ 非纯函数
slice()splice()
map()改动外部变量
返回新对象修改全局/参数

纯函数为什么重要?

  • 可测试性高

  • 结果可预测

  • React reducer 必须是纯函数(重要面试点)


四、柯里化(Currying)

定义:将多参函数转为链式调用,每次接收一个参数。

const add = a => b => c => a + b + c;

为什么需要柯里化?

好处场景
参数复用logger('INFO')('msg')
拆分逻辑单一职责
延迟执行fn(a)(b)(c)

自动柯里化(只需要理解遇见了可以用就行了)

function curry(fn) { 
    return function curried(...args) { 
        if(args.length >= fn.length) 
            return fn(...args) 
                return (...rest) => curried(...args, ...rest) 
        } 
}

五、组合函数(Compose)

定义:让多个函数依次执行,类似链式函数管道。

const compose = (f, g) => x => f(g(x));

前端框架应用:Redux、函数式工具库(Ramda、lodash/fp)


六、with & eval(面试常问:为什么不用?)

with 不推荐使用

  • 修改作用域链 → 难定位变量来源 → 性能差 / 易错

eval 不推荐使用

问题原因
安全风险可注入攻击
性能差无法被 JS 引擎优化
可读性差难调试

面试答案:with 和 eval 都破坏作用域、风险大、性能差,因此禁用


七、严格模式(use strict)

开启方式

"use strict"; // 文件或函数顶部

作用

优点说明
异常更明确抛出错误避免 silent fail
禁止意外全局变量x = 10 // error
this 不自动绑定 window函数 this = undefined
禁止 with / 限制 eval更安全

默认开启位置

  • class

  • module

面试口诀:“严格模式 = 更安全 + 更规范 + 更利于引擎优化”


对象增强:Object.defineProperty & 属性描述符

一、defineProperty 基本用法

Object.defineProperty(
obj, 
"name", 
{ value: "coder", writable: false, enumerable: false, configurable: false }
)

二、属性描述符分类

1)数据属性(value)

属性说明默认值
value属性值undefined
writable是否可修改false
enumerable是否可枚举false
configurable是否可配置false

1 当我们直接在一个对象上定义某个属性时,这个属性的以上熟悉默认为true

2 当我们通过属性描述符定义一个属性时,这个属性的数据属性默认为以上表格值

configurable表示属性是否可以通过delete删除属性,是否可以修改它的特性,或者是否可以将它修改为存取属性描述符


2)存取属性(get/set)

Object.defineProperty(obj,"age",{ get(){...}, set(val){...} })
特性说明
get获取属性触发
set设置属性触发

面试点:不能同时定义 value/writable 与 get/set


三、defineProperties(批量)

Object.defineProperties(obj, { name:{value:'a'}, age:{value:18} })

四、对象操作方法对比

方法作用
getOwnPropertyDescriptor获取单个属性描述符
getOwnPropertyDescriptors获取全部属性描述符
preventExtensions禁止添加新属性
seal禁止新增/删除属性
freezeseal + 不允许修改属性值

面试速记清单 ✅

主题记忆点
arguments vs restrest 真数组 ✅ arguments 旧时代 ❌
纯函数确定输入 → 确定输出,无副作用
副作用例子修改外部变量、I/O、DOM、Math.random
柯里化fn(a)(b)(c),参数复用+函数拆分
compose函数组合执行 pipeline
严格模式禁全局变量、禁 with、优化引擎
属性描述符value/writable/enumerable/configurable
存取属性get/set,不与 value 同时存在
freeze/seal/preventExtensions限制对象可扩展性层级

JavaScript 函数 & 对象高频面试 标准答案模板(可直接背诵)

1)arguments vs rest 参数

标准回答:

arguments 是类数组对象,用于获取所有实参,但缺乏数组方法,且箭头函数无法访问。
ES6 引入 rest 参数 (...args),是真数组、更语义化、更推荐使用。

总结口诀:

能用 rest,不用 arguments。


2)什么是纯函数?为什么重要?

标准回答:

纯函数是指给定相同输入永远返回相同输出,且无副作用的函数。
它不修改外部状态,不依赖全局环境。
在 React/Redux 中,reducer 必须是纯函数以保证可预测性和可测试性。

副作用例子:
修改全局变量、DOM 操作、I/O、setTimeout、Date、Math.random


3)解释柯里化及应用场景

标准回答:

柯里化是将多参函数转为单参链式调用的技术,可复用参数、拆分逻辑、实现函数组合与延迟计算。

例:sum(1)(2)(3)

场景:日志封装、权限校验、定制请求器


4)compose 函数作用

标准回答:

compose 实现函数组合,将多个函数从右向左依次执行,常用于数据管道与 Redux 中间件构建。


5)为什么不推荐 with & eval

with 修改词法作用域链 → 难维护 + 性能差
eval 执行字符串为代码 → 安全风险 + 性能差 + 无法 JIT 优化


6)严格模式的意义

防止隐式全局变量
禁止 with
this 不再指向 window(函数中为 undefined)
更利于 JS 引擎优化


7)Object.defineProperty 的作用

自定义属性行为,包括可写性(writable)、可枚举性(enumerable)、可配置性(configurable),以及 getter/setter。


8)对象冻结与扩展性方法

方法新增删除改值
preventExtensions❌✅✅
seal❌❌✅
freeze❌❌❌ ✅只读

口诀:

freeze > seal > preventExtensions


✅ 二、手写代码大题答案(面试必考)

1)手写 call

Function.prototype.myCall = function(ctx, ...args) {
  ctx = ctx || window;
  const key = Symbol();
  ctx[key] = this;
  const res = ctx[key](...args);
  delete ctx[key];
  return res;
}

2)手写 bind

Function.prototype.myBind = function(ctx, ...args) {
  const fn = this;
  return function(...rest) {
    return fn.apply(ctx, [...args, ...rest]);
  };
}

3)手写柯里化 curry

function curry(fn){
  return function curried(...args){
    if(args.length >= fn.length) return fn(...args);
    return (...rest) => curried(...args, ...rest);
  }
}

4)compose 函数

const compose = (...fns) => arg =>
  fns.reduceRight((prev, fn) => fn(prev), arg);

 

 

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐