Effective JavaScript Item 28 不要依赖函数的toString方法

本系列作为Effective JavaScript的读书笔记。

在JavaScript中,函数对象上存在一个toString方法,它能够方便地将函数的源代码转换返回成一个字符串对象。

(function(x) {
	return x + 1;
}).toString(); // "function (x) {\n return x + 1;\n}"

toString方法不仅仅会让一些黑客找到攻击的方法,而且该方法也存在严重的限制。

首先,toString方法的实现方式并没有被ECMAScript规范化,因此各种JavaScript的执行引擎中的toString的实现方式也许会不一致。

其次,当toString能够返回函数源代码并且函数本身完全以JavaScript实现时,源代码才会被正确的返回。比如,在以下的函数调用了,使用了bind方法得到了一个新的函数对象(关于bind的使用方式,可以参考Item
25, 26):

(function(x) {
	return x + 1;
}).bind(16).toString(); // "function (x) {\n [native code]\n}"

可以发现,返回的字符串中有一段是[nativecode],这是因为在很多JavaScript执行环境中,bind方法都是使用其他编程语言如C++来实现的。因此这里看到native
code实际上就是代表着一段编译后的C++源码。

最后,toString方法返回的源代码体现不了传入参数的值:

(function(x) {
	return function(y) {
		return x + y;
	}
})(42).toString(); // "function (y) {\n return x + y;\n}"

上述代码中传入的参数42在返回的函数源代码中并没有被体现出来。

因为以上的这些限制,使toString方法很难正确和可靠地被使用。在实际应用中,应该尽量避免使用它。

总结:

  1. ECMAScript标准并没有对函数的toString的实现方式作出规范。
  2. 因为toString在各种平台上存在着不一致的行为,尽量不要使用它。

时间: 2024-10-12 03:57:50

Effective JavaScript Item 28 不要依赖函数的toString方法的相关文章

读书笔记 effective c++ Item 35 考虑虚函数的替代者

1. 突破思维——不要将思维限定在面向对象方法上 你正在制作一个视频游戏,你正在为游戏中的人物设计一个类继承体系.你的游戏处在农耕时代,人类很容易受伤或者说健康度降低.因此你决定为其提供一个成员函数,healthValue,返回一个整型值来表明一个人物的健康度.因为不同的人物会用不同的方式来计算健康度,将healthValue声明为虚函数看上去是一个比较明显的设计方式: 1 class GameCharacter { 2 public: 3 4 virtual int healthValue()

Effective JavaScript Item 25 使用bind方法来得到一个固定了this指向的方法

本系列作为Effective JavaScript的读书笔记. 当需要将方法抽取出来作为回调函数使用的时候,常常会因为this的指向不明而发生错误,比如: var buffer = { entries: [], add: function(s) { this.entries.push(s); }, concat: function() { return this.entries.join(""); } }; 如果想利用其中的add作为回调函数对一组数据进行添加: var source

Effective C++ Item 35 考虑 virtual 函数以外的实现

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 1.virtual 函数版本 class GameCharacter{ public: virtual int healthValue() const; //返回人物的健康指数, derived classes 可重新定义它 }; 2.使用 non-virtual interface 手法,那是 Template Method 设计模式的一种特殊形式. 让客户通过 public non-v

Effective C++ Item 45 运用成员函数模板接收所有兼容类型

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 经验:请使用 member function templates(成员函数模板)生成"可接受所有兼容类型"的函数 示例:泛化 copy 构造函数 temmplate<typename T> class SmartPtr{ public: template<typename U> SmartPtr(const SmartPtr<U> &o

Effective JavaScript Item 26 使用bind来进行函数的柯里化(Curry)

本系列作为Effective JavaScript的读书笔记. 在上一个Item中介绍了bind的一种用法:用来绑定this对象.但是实际上,bind含有另一种用法,就是帮助函数进行柯里化.关于柯里化,这里有一份百科可以参考: http://zh.wikipedia.org/wiki/%E6%9F%AF%E9%87%8C%E5%8C%96 但是实际上,关于柯里化只需要记住一点就够了:柯里化是把接受多个参数的函数变换成接受一个单一参数(通常是最初函数的第一个参数,但是并无限制)的函数,并且返回这个

Effective JavaScript Item 13 使用即时调用的函数表达式(IIFE)来创建局部域

本系列作为Effective JavaScript的读书笔记. 所谓的即时调用的函数表达式,这个翻译也许不太准确,它对应的英文原文是Immediately Invoked Function Expression (IIFE).下文也使用IIFE来表达这一概念. 首先看一个程序: function wrapElements(a) { var result = [], i, n; for (i = 0, n = a.length; i < n; i++) { result[i] = function

Effective JavaScript Item 22 使用arguments来创建接受可变参数列表的函数

本系列作为Effective JavaScript的读书笔记. 在Item 21中,介绍了结合apply方法实现的可变参数列表函数average,它实际上只声明了一个数组作为参数,但是利用apply方法,实际上可以接受若干元素作为参数: function averageOfArray(a) { for (var i = 0, sum = 0, n = a.length; i < n; i++) { sum += a[i]; } return sum / n; } averageOfArray.a

Effective JavaScript Item 21 使用apply方法调用函数以传入可变参数列表

本系列作为Effective JavaScript的读书笔记. 下面是一个拥有可变参数列表的方法的典型例子: average(1, 2, 3); // 2 average(1); // 1 average(3, 1, 4, 1, 5, 9, 2, 6, 5); // 4 average(2, 7, 1, 8, 2, 8, 1, 8); // 4.625 而以下则是一个只接受一个数组作为参数的例子: averageOfArray([1, 2, 3]); // 2 averageOfArray([1

Effective JavaScript Item 19 使用高阶函数 (High-Order Function)

本系列作为Effective JavaScript的读书笔记. 不要被高阶函数这个名字给唬住了.实际上,高阶函数只是代表了两类函数: 接受其他函数作为参数的函数 返回值为函数的函数 有了这个定义,你也许就发现你已经使用过它们了,典型的就是对于一些事件的处理时传入的回调函数. 另外的一个典型使用场景就是Array类型的sort函数,它可以接受一个function作为排序时比较的判断依据: [3, 1, 4, 1, 5, 9].sort(function(x, y) { if (x < y) { r