Effective JavaScript Item 23 永远不要修改arguments对象
本系列作为Effective JavaScript的读书笔记。
arguments对象只是一个类似数组的对象,但是它并没有数组对象提供的方法,比如shift,push等。因此调用诸如:arguments.shift(),arguments.push()是错误的。
在Item 20和Item 21中,知道了函数对象上存在call和apply方法,那么是不是可以利用它们来让arguments也能够利用数组的方法呢:
function callMethod(obj, method) {var shift = [].shift;shift.call(arguments);shift.call(arguments);return obj[method].apply(obj, arguments);
}
但是以上的方法在下面的应用场景中存在问题:
var obj = {add: function(x, y) { return x + y; }
};
callMethod(obj, "add", 17, 25);
// error: cannot read property "apply" of undefined
发生错误的原因是:
arguments对象并不是函数参数的一份拷贝。函数声明的参数和arguments保存的对象存在着引用关系。比如在上面callMethod函数的例子中,声明了两个参数obj和method:
obj引用的就是arguments[0]
method引用的就是arguments[1]
而在调用了两次shift.call(arguments)之后,arguments由原来的:
[obj, "add", 17, 25]变成了[17, 25]
所以obj的引用从obj本身变成了17,method的引用从"add"变成了25。很显然17[25]得到的结果是undefined,因为根据JavaScript的运算规则,17首先会被转换为Number对象,而这个对象之上并没有25这个属性。
上述例子想表达的就是,函数中声明的参数和arguments之间的联系很脆弱,每个声明的参数实际上只是对arguments对象中对应位置的一个引用。
值得注意的是,在ES5的strict mode中,函数声明的参数并不会引用arguments:
function strict(x) {"use strict";arguments[0] = "modified";return x === arguments[0];
}
function nonstrict(x) {arguments[0] = "modified";return x === arguments[0];
}
strict("unmodified"); // false
nonstrict("unmodified"); // true
正因为在strict和非strict模式下,函数声明的参数和arguments的关系不一致,所以为了避免出现问题,不去修改arguments对象才是最安全的做法。
如果确实需要修改arguments对象,那么可以首先赋值一份arguments对象:
var args = [].slice.call(arguments);
当slice方法不接受任何参数的时候,就会执行复制操作,得到的args也是一个真正的数组对象。同时,args和函数声明的参数之间也没有任何联系了,对它进行操作是安全的。使用这种方式重新实现上面提到过的callMethod函数:
function callMethod(obj, method) {var args = [].slice.call(arguments, 2);return obj[method].apply(obj, args);
}var obj = {add: function(x, y) { return x + y; }
};
callMethod(obj, "add", 17, 25); // 42
总结:
- 永远不要修改arguments对象
- 使用[].slice.call(arguments)得到arguments对象的一份拷贝,然后对拷贝进行修改
Effective JavaScript Item 23 永远不要修改arguments对象相关推荐
- [Effective JavaScript 笔记]第23条:永远不要修改arguments对象
arguments对象并不是标准的Array类型的实例.arguments对象不能直接调用Array方法. arguments对象的救星call方法 使得arguments可以品尝到数组方法的美味,知 ...
- JavaScript学习(五十七)— arguments对象
JavaScript学习(五十七)- arguments对象 arguments对象 该对象是函数内部的一个属性,这个属性本身也是一个对象 这个对象是用来管理函数被调用时传过来的实参的 argumen ...
- Effective JavaScript Item 37 认识this的隐式指向
本系列作为Effective JavaScript的读书笔记. CSV数据通常都会被某种分隔符进行分隔.所以在实现CSV Reader时,须要支持不同的分隔符.那么,非常自然的一种实现就是将分隔符作为 ...
- Effective JavaScript Item 40 避免继承标准类型
本系列作为Effective JavaScript的读书笔记. ECMAScript标准库不大.可是提供了一些重要的类型如Array,Function和Date.在一些场合下.你或许会考虑继承当中的某 ...
- Effective JavaScript Item 33 让构造函数不再依赖newkeyword
本系列作为EffectiveJavaScript的读书笔记. 在将function当做构造函数使用时,须要确保该函数是通过newkeyword进行调用的. function User(name, pa ...
- Effective C#: Item 1 Always use properties instead of accessible data members
Effective C#: Item 1 Always use properties instead of accessible data members Item 1: 当设计类时,永远用Prope ...
- JavaScript学习系列3 -- JavaScript arguments对象学习
在实际项目开发中,目前还是很少使用到JavaScript 中的arguments对象,那么它到底是干什么用的呢 arguments是JavaScript中的一个类数组对象,它代表传给一个正在执行的函数 ...
- [Effective JavaScript 笔记]第27条:使用闭包而不是字符串来封装代码
函数是一种将代码作为数据结构存储的便利方式,代码之后可以被执行.这使得富有表现力的高阶函数抽象如map和forEach成为可能.它也是js异步I/O方法的核心.与此同时,也可以将代码表示为字符串的形式 ...
- 你知道 JavaScript 中的 Arguments 对象都有哪些用途吗?
JavaScript 中 Arguments 对象的用途总结. 前言 相信我们很多人在代码开发的过程中都使用到过一个特殊的对象 -- Arguments 对象. 在实际开发中,Arguments 对象 ...
最新文章
- python在bim中的应用_Revit元素类别——Dynamo Python系列教程(六)
- (原)Apache添加完限速模块后的文件
- linux 修改ssh banner
- [SQLITE_READONLY] Attempt to write a readonly databse (attempt to write a readonly database)
- 前端学习(2123):知识回顾
- 并发系列(二)----Java内存模型
- 9.20 模拟试题
- 2018级C语言大作业 - 祖玛
- python list append 相关知识点
- 题解 洛谷 P1580 【yyy loves Easter_Egg I】
- APP开发内容介绍(源代码)
- leetcode845. 数组中的最长山脉
- linux samba 漏洞 exp,smaba漏洞总结
- Excel表格导入CAD后,表格内数字后的小数点怎么消除呢?
- 【向生活低头】十分白痴地自动删微博文章脚本
- PCB设计中常用class与subclass
- 学习乐器的好处(1)
- 苹果 WWDC 2019 全记录:iPadOS独立、SwiftUI、Project Catalyst
- 阴阳师真八歧大蛇最低配置攻略,蛇黑切
- HTTP协议实现文件下载
热门文章
- 秒杀抢单系统软件架构优化思路
- 当RxJava遇上Retrofit
- “二老板”何以疯行互联网?
- verilog always语法_Verilog 最全经验总结(建议收藏)
- 访问控制模型详细介绍
- 名果黑的Mac装机必备
- 记录谷歌gn编译时碰到的一个错误“I could not find a “.gn“ file ...”
- 打蚊子表情包_蚊子表情包 - 蚊子微信表情包 - 蚊子QQ表情包 - 发表情 fabiaoqing.com...
- Centos7下的LibreOffice的搭建及自动化脚本部署
- 洛谷 P2071 座位安排 (最大流 + 建图)