红茶的个人站点

  • 首页
  • 专栏
  • 开发工具
  • 其它
  • 隐私政策
Awalon
Talk is cheap,show me the code.
  1. 首页
  2. 前端学习笔记
  3. 正文

JavaScript 学习笔记 11:其它

2026年4月20日 5点热度 0人点赞 0条评论

Eval

eval可以执行一段 JS 代码片段:

eval("console.log('hello world')");

eval可以执行多行语句,返回的结果时最后一条语句的结果:

let result = eval("let i=0;++i;");
console.log(result);
// 1

eval的词法环境包含于当前的词法环境,因此可以访问外部变量:

let name = 'Jack';
eval("console.log('hello ' + name)");
// hello Jack

甚至是修改外部变量:

let name = 'Jack';
let age = 18;
eval(`
age++;
console.log('hello ' + name + ' ' + age);
`);
// hello Jack 19

eval有自己的词法环境,外部不能访问eval内部的变量:

eval("function hello() {console.log('hello world')}");
hello();
// ReferenceError: hello is not defined

在严格模式下才生效,比如use strict或模块中。

在现代 JS 中,一般不需要使用eval,且eval存在一个严重问题,现代 JS 一般都会使用 JS 压缩,压缩后的 JS 代码中的变量名会被重命名,如果eval中有对外部变量的读写,就可能出错。

柯里化

柯里化是一种函数转换,可以将f(a,b,c)转换为f(a)(b)(c):

function curry(fn){
    return function (a){
        return function (b){
            return fn(a,b);
        }
    }
}
​
function add(a,b){
    return a+b;
}
​
let curryAdd = curry(add);
console.log(curryAdd(1)(2));

有很多第三方库都提供柯里化的工具函数,比如lodash:

function add(a, b) {
    return a + b;
}
​
let _ = require('lodash');
let curryAdd = _.curry(add);
console.log(curryAdd(1)(2));
console.log(curryAdd(1, 2));

柯里化的好处是我们可以利用其特点很容易地快速创建新的函数:

let _ = require('lodash');
function log(date, level, message){
    console.log(`${date} [${level}]: ${message}`);
}
​
let curryLog = _.curry(log);
let todayLog = curryLog(new Date());
let todayInfo = todayLog('INFO');
let todayError = todayLog('ERROR');
todayInfo('hello world');
todayError('hello world');
// Mon Apr 20 2026 15:36:33 GMT+0800 (中国标准时间) [INFO]: hello world
// Mon Apr 20 2026 15:36:33 GMT+0800 (中国标准时间) [ERROR]: hello world

如果不想使用第三方库,要手动实现多参数的柯里化:

function curry(fn){
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.apply(this, args);
        } else {
            return function (...args2) {
                return curried.apply(this, args.concat(args2));
            }
        }
    }
}
​
function add(a, b, c) {
    return a + b + c;
}
​
let curryAdd = curry(add);
console.log(curryAdd(1)(2)(3));
console.log(curryAdd(1, 2)(3));
console.log(curryAdd(1, 2, 3));

引用类型

会出现丢失this的情况:

let user = {
    _name: 'Mike',
    getName() { 
        return this._name;
    }
}
​
console.log(user.getName());
// Mike
let getName = user.getName;
console.log(getName());
// TypeError: Cannot read properties of undefined (reading '_name')

直接调用对象方法没有问题,但如果将对象方法赋值给额外变量,再调用变量就会报错,因为此时this是undefined。

原因是使用.操作符获取到的对象方法user.getName返回的其实是一个 JS 使用的内部类型,该类型包含三部分内容:

(user, "getName", true)

因此获取引用对象后直接调用时可以获取到正确的this:

user.getName()

但如果赋值,结果会变成对象方法,this对应的user对象被丢弃。

可以使用func.bind解决这个问题:

let user = {
    _name: 'Mike',
    getName() { 
        return this._name;
    }
}
​
console.log(user.getName());
// Mike
let getName = user.getName.bind(user);
console.log(getName());

The End.

本文的完整示例代码可以从这里获取。

参考资料

  • 现代 JavaScript 教程

本作品采用 知识共享署名 4.0 国际许可协议 进行许可
标签: 暂无
最后更新:2026年4月20日

魔芋红茶

加一点PHP,加一点Go,加一点Python......

点赞
< 上一篇

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

COPYRIGHT © 2021 icexmoon.cn. ALL RIGHTS RESERVED.
本网站由提供CDN加速/云存储服务

Theme Kratos Made By Seaton Jiang

宁ICP备2021001508号

宁公网安备64040202000141号