勿乱动arguments对象

本文涉及的产品
云数据库 Redis 版,社区版 2GB
推荐场景:
搭建游戏排行榜
简介: 此题是看到51js论坛上有人提出这个问题:求解arguments对象的内部实现原理 真正不在于提的问题本身,而在于不同的浏览器对它的实现并不完全一致。直接上代码了: 1: function chrome_bug(a, b) { 2: arguments[1] = 2;...

此题是看到51js论坛上有人提出这个问题:求解arguments对象的内部实现原理

真正不在于提的问题本身,而在于不同的浏览器对它的实现并不完全一致。直接上代码了:

   1: function chrome_bug(a, b) {
   2:        arguments[1] = 2;
   3:        alert(b); // Chrome:2, other:undefined
   4: }
   5:  
   6: chrome_bug(1);

到底是chrome的bug还是其它浏览器实现的并不“标准”呢?还是翻翻标准…

关于Arguments Object (证明chrome是接近标准的,其它浏览器不知道为何没这么实现~ ~)

 

10.1.8 Arguments Object

When control enters an execution context for function code, an arguments object is created and initialised as follows:

  • The value of the internal [[Prototype]] property of the arguments object is the original Object prototype object, the one that is the initial value of Object.prototype (see 15.2.3.1).
  • A property is created with name callee and property attributes { DontEnum }. The initial value of this property is the Function object being executed. This allows anonymous functions to be recursive.
  • A property is created with name length and property attributes { DontEnum }. The initial value of this property is the number of actual parameter values supplied by the caller.
  • For each non-negative integer, arg, less than the value of the length property, a property is created with name ToString(arg) and property attributes { DontEnum }. The initial value of this property is the value of the corresponding actual parameter supplied by the caller. The first actual parameter value corresponds to arg = 0, the second to arg = 1, and so on. In the case when arg is less than the number of formal parameters for the Function object, this property shares its value with the corresponding property of the activation object. This means that changing this property changes the corresponding property of the activation object and vice versa.

 

再来几个例子:

   1: <script type='text/javascript'>
   2:     ~function(a){
   3:         var a= 'false';
   4:         alert(arguments[0]);//都输出'false'
   5:     }(true);
   6: </script>

 

   1: <script type='text/javascript'>
   2:     ~function(a){
   3:         Array.prototype.splice.call(arguments,0,1);
   4:         alert(a);//chrome为'undefined' 其它浏览器为 1
   5:     }(1);
   6: </script>
 
   1: <script type='text/javascript'>
   2:     ~function(a, b) {
   3:         arguments[1] = 2;
   4:         alert(b);//chrome为2 其它浏览器为'undefined'
   5:     }(1);
   6: </script>

 

从上面几个例子上看,感觉chrome中arguments[1]的引用指向了实参,改变arguments[1]或是b都将互相影响,验证一把:

   1: <script type='text/javascript'>
   2:     ~function(a, b) {
   3:         arguments[1] = 2;
   4:         b = 3;
   5:         alert(arguments[1]);//chrome为3 其它浏览器为2
   6:     }(1);
   7: </script>

 

 

既然发现浏览器间的实现不完全一致,所以还是觉得在开发少折腾arguments对象了。

 

 

好吧,想前之前好像在本机编译过v8的源码,翻出来看看(不过c++差不多已经还给老师了,本来就没学好~ ~!!有空再恶补一下)

在v8_base的src目录下找到了“arguments.h”头文件:

   1: // Copyright 2006-2008 the V8 project authors. All rights reserved.
   2: // Redistribution and use in source and binary forms, with or without
   3: // modification, are permitted provided that the following conditions are
   4: // met:
   5: //
   6: //     * Redistributions of source code must retain the above copyright
   7: //       notice, this list of conditions and the following disclaimer.
   8: //     * Redistributions in binary form must reproduce the above
   9: //       copyright notice, this list of conditions and the following
  10: //       disclaimer in the documentation and/or other materials provided
  11: //       with the distribution.
  12: //     * Neither the name of Google Inc. nor the names of its
  13: //       contributors may be used to endorse or promote products derived
  14: //       from this software without specific prior written permission.
  15: //
  16: // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  17: // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  18: // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  19: // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  20: // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  21: // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  22: // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  23: // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  24: // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  25: // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  26: // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  27:  
  28: #ifndef V8_ARGUMENTS_H_
  29: #define V8_ARGUMENTS_H_
  30:  
  31: namespace v8 {
  32: namespace internal {
  33:  
  34: // Arguments provides access to runtime call parameters.
  35: //
  36: // It uses the fact that the instance fields of Arguments
  37: // (length_, arguments_) are "overlayed" with the parameters
  38: // (no. of parameters, and the parameter pointer) passed so
  39: // that inside the C++ function, the parameters passed can
  40: // be accessed conveniently:
  41: //
  42: //   Object* Runtime_function(Arguments args) {
  43: //     ... use args[i] here ...
  44: //   }
  45:  
  46: class Arguments BASE_EMBEDDED {
  47:  public:
  48:   Arguments(int length, Object** arguments)
  49:       : length_(length), arguments_(arguments) { }
  50:  
  51:   Object*& operator[] (int index) {
  52:     ASSERT(0 <= index && index < length_);
  53:     return arguments_[-index];
  54:   }
  55:  
  56:   template <class S> Handle<S> at(int index) {
  57:     Object** value = &((*this)[index]);
  58:     // This cast checks that the object we're accessing does indeed have the
  59:     // expected type.
  60:     S::cast(*value);
  61:     return Handle<S>(reinterpret_cast<S**>(value));
  62:   }
  63:  
  64:   // Get the total number of arguments including the receiver.
  65:   int length() const { return length_; }
  66:  
  67:   Object** arguments() { return arguments_; }
  68:  
  69:  private:
  70:   int length_;
  71:   Object** arguments_;
  72: };
  73:  
  74:  
  75: // Cursom arguments replicate a small segment of stack that can be
  76: // accessed through an Arguments object the same way the actual stack
  77: // can.
  78: class CustomArguments : public Relocatable {
  79:  public:
  80:   inline CustomArguments(Object* data,
  81:                          JSObject* self,
  82:                          JSObject* holder) {
  83:     values_[3] = self;
  84:     values_[2] = holder;
  85:     values_[1] = Smi::FromInt(0);
  86:     values_[0] = data;
  87:   }
  88:   void IterateInstance(ObjectVisitor* v);
  89:   Object** end() { return values_ + 3; }
  90:  private:
  91:   Object* values_[4];
  92: };
  93:  
  94:  
  95: } }  // namespace v8::internal
  96:  
  97: #endif  // V8_ARGUMENTS_H_

 

 

 

本文参考:

Google Chrome雷区之二--莫动arguments对象

ECMAScript Language Specification

V8 JavaScript Engine

相关实践学习
基于Redis实现在线游戏积分排行榜
本场景将介绍如何基于Redis数据库实现在线游戏中的游戏玩家积分排行榜功能。
云数据库 Redis 版使用教程
云数据库Redis版是兼容Redis协议标准的、提供持久化的内存数据库服务,基于高可靠双机热备架构及可无缝扩展的集群架构,满足高读写性能场景及容量需弹性变配的业务需求。 产品详情:https://www.aliyun.com/product/kvstore &nbsp; &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
3月前
|
JSON 前端开发 JavaScript
【面试题】面试官:请你实现一个深拷贝,那如果是正则/set/函数怎么拷贝?
【面试题】面试官:请你实现一个深拷贝,那如果是正则/set/函数怎么拷贝?
|
8月前
_proto__ 、prototype傻傻分不清楚?
_proto__ 、prototype傻傻分不清楚?
|
10月前
|
JavaScript 前端开发
熬夜整理的 Object 对象的静态方法、实例属性和实例方法
熬夜整理的 Object 对象的静态方法、实例属性和实例方法,用于理解 Object 对象的静态方法和实例方法的区别,以及 Object 对象的静态方法和实例方法的使用。
67 0
|
10月前
|
存储 JavaScript 前端开发
📕 重学JavaScript:函数的入参(arguments)是什么类型?我能怎么使用它?
arguments是一个特殊的对象👏,它可以存储我们给函数传递的所有参数。只不过它的属性从0开始排,依次为0,1,2…最后还有callee和length属性。我们也把这样的对象称为类数组。
70 0
|
11月前
|
JavaScript 前端开发
|
11月前
|
JavaScript 前端开发
|
JavaScript 前端开发 测试技术
学习TypeScrip13(symbol类型)
我们平时开发中不会手动调用iterator 应为 他是有语法糖的就是for of 记住 for of 是不能循环对象的应为对象没有 iterator
92 0