JavaScript全局函数研究_手写模仿实现_01:eval、isFinite、isNaN、parseFloat、parseInt

JavaScript全局函数研究_手写模仿实现:eval、isFinite、isNaN、parseFloat、parseInt

JavaScript提供了一系列全局函数,用于在不同的场景下处理数据。这些函数包括evalisFiniteisNaNparseFloatparseInt等。理解这些函数的工作原理,有助于我们更深入地掌握JavaScript的核心机制。本文将逐一介绍这些全局函数的作用,并尝试手写模仿它们的实现,深入剖析其内部逻辑。

一、eval()

1. 基础介绍

eval()函数接收一个字符串作为参数,将其作为JavaScript代码执行。它可以动态地执行字符串形式的代码,这在某些动态场景下非常有用。然而,由于安全和性能问题,通常不建议使用eval()

2. 语法

eval(string)
  • string:要执行的字符串代码。

3. 示例代码

const code = 'console.log("Hello, World!");';
eval(code); // 输出: Hello, World!

4. 手写模仿实现

由于eval()是JavaScript引擎内置的解析器功能,无法完全手写实现其功能。但我们可以模拟eval()的一些简单场景,例如执行基本的数学表达式解析。

示例:简单的数学表达式求值
function simpleEval(expr) {
  // 只允许数字和基本运算符,防止安全问题
  if (/^[\d+\-*/\s()]+$/.test(expr)) {
    return new Function(`return ${expr}`)();
  } else {
    throw new Error('Invalid expression');
  }
}

console.log(simpleEval('2 + 3 * (4 - 1)')); // 输出: 11

注意:上面的实现使用了new Function(),它与eval()类似,也存在安全隐患。在生产环境中,应避免执行来自不可信来源的代码。

5. 安全与性能考虑

  • 安全性eval()可能执行恶意代码,导致安全漏洞。
  • 性能eval()在执行时需要调用解释器,可能会降低性能。
  • 替代方案:通常可以通过其他方式实现同样的功能,例如使用对象映射、函数调用等。

二、isFinite()

1. 基础介绍

isFinite()函数用于判断一个值是否为有限数值。当参数转换为数字类型后,如果是有限数字,则返回true,否则返回false

2. 语法

isFinite(value)
  • value:要检测的值。

3. 示例代码

console.log(isFinite(100));        // 输出: true
console.log(isFinite('200'));      // 输出: true(字符串会被转换为数字)
console.log(isFinite(Infinity));   // 输出: false
console.log(isFinite(NaN));        // 输出: false

4. 手写模仿实现

function myIsFinite(value) {
  const num = Number(value);
  return typeof num === 'number' && !isNaN(num) && num !== Infinity && num !== -Infinity;
}

console.log(myIsFinite(100));        // 输出: true
console.log(myIsFinite('200'));      // 输出: true
console.log(myIsFinite(Infinity));   // 输出: false
console.log(myIsFinite(NaN));        // 输出: false

5. 实现原理

  • 首先,将传入的值转换为数字类型。
  • 检查类型是否为number,并排除NaNInfinity-Infinity

三、isNaN()

1. 基础介绍

isNaN()函数用于判断一个值是否为NaN(非数字值)。当参数转换为数字后,如果结果是NaN,则返回true,否则返回false

2. 语法

isNaN(value)
  • value:要检测的值。

3. 示例代码

console.log(isNaN(NaN));          // 输出: true
console.log(isNaN('hello'));      // 输出: true('hello'转换为数字是NaN)
console.log(isNaN(123));          // 输出: false
console.log(isNaN('456'));        // 输出: false

4. 手写模仿实现

function myIsNaN(value) {
  const num = Number(value);
  return num !== num;
}

console.log(myIsNaN(NaN));          // 输出: true
console.log(myIsNaN('hello'));      // 输出: true
console.log(myIsNaN(123));          // 输出: false
console.log(myIsNaN('456'));        // 输出: false

5. 实现原理

  • 将值转换为数字。
  • 利用NaN不等于自身的特性,即NaN !== NaNtrue

注意:ES6引入了Number.isNaN(),它更为严格,只在参数为NaN时返回true

console.log(Number.isNaN('hello')); // 输出: false

四、parseFloat()

1. 基础介绍

parseFloat()函数解析一个字符串参数,并返回一个浮点数。如果字符串的第一个字符不能被转换为数字,则返回NaN

2. 语法

parseFloat(string)
  • string:要解析的字符串。

3. 示例代码

console.log(parseFloat('3.14'));      // 输出: 3.14
console.log(parseFloat('10e2'));      // 输出: 1000
console.log(parseFloat('  -5.5 '));   // 输出: -5.5
console.log(parseFloat('abc'));       // 输出: NaN

4. 手写模仿实现

function myParseFloat(str) {
  const regex = /^\s*([+-]?(\d+(\.\d*)?|\.\d+)([eE][+-]?\d+)?)\s*/;
  const match = str.match(regex);
  if (match) {
    return Number(match[1]);
  } else {
    return NaN;
  }
}

console.log(myParseFloat('3.14'));      // 输出: 3.14
console.log(myParseFloat('10e2'));      // 输出: 1000
console.log(myParseFloat('  -5.5 '));   // 输出: -5.5
console.log(myParseFloat('abc'));       // 输出: NaN

5. 实现原理

  • 使用正则表达式匹配浮点数格式。
  • 提取匹配的数值字符串并转换为数字。
  • 处理前导和后续的空白字符。

五、parseInt()

1. 基础介绍

parseInt()函数解析一个字符串参数,并返回一个指定基数的整数。如果字符串的第一个字符不能被转换为数字,则返回NaN

2. 语法

parseInt(string, [radix])
  • string:要解析的字符串。
  • radix(可选):表示要解析的数字的基数(2 ~ 36)。

3. 示例代码

console.log(parseInt('42'));           // 输出: 42
console.log(parseInt('1010', 2));      // 输出: 10(二进制)
console.log(parseInt('ff', 16));       // 输出: 255(十六进制)
console.log(parseInt('0x10'));         // 输出: 16
console.log(parseInt('abc'));          // 输出: NaN

4. 手写模仿实现

function myParseInt(str, radix) {
  str = String(str).trim();
  radix = radix || 0;

  const regexHex = /^[-+]?0[xX][\dA-Fa-f]+$/;
  const regexOct = /^[-+]?0[oO][0-7]+$/;
  const regexBin = /^[-+]?0[bB][01]+$/;

  if (radix === 0) {
    if (regexHex.test(str)) radix = 16;
    else if (regexOct.test(str)) radix = 8;
    else if (regexBin.test(str)) radix = 2;
    else radix = 10;
  }

  const regex = new RegExp(`^[-+]?([\\dA-Za-z]+)`);
  const match = str.match(regex);

  if (match) {
    const numStr = match[0];
    return Number.parseInt(numStr, radix);
  } else {
    return NaN;
  }
}

console.log(myParseInt('42'));           // 输出: 42
console.log(myParseInt('1010', 2));      // 输出: 10
console.log(myParseInt('ff', 16));       // 输出: 255
console.log(myParseInt('0x10'));         // 输出: 16
console.log(myParseInt('abc'));          // 输出: NaN

5. 实现原理

  • 将输入转换为字符串并去除空白字符。
  • 处理radix参数,确定进制。
  • 使用正则表达式提取有效的数字部分。
  • 利用Number.parseInt()进行数值转换。

注意:在ECMAScript规范中,parseInt()radix0或未提供时,会根据字符串内容自动判断进制。

注意事项

  • 安全性:避免使用eval()new Function()执行不可信的代码。
  • 类型转换isFinite()isNaN()会进行隐式类型转换,需要注意输入类型。
  • 进制处理parseInt()radix参数非常重要,可能影响结果,需要明确指定。

参考资料


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

It'sMyGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值