勿乱动arguments对象

此题是看到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

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏鸿的学习笔记

Python写的Python解释器(五)

条件和循环 到目前为止,解释器仅仅只是简单的逐个执行指令。下面将会讲述需要多次执行某些指令,或者在特定条件下跳过它们的做法。在代码中编写循环和if语句时,解释器...

11920
来自专栏跟着阿笨一起玩NET

[C#]工具类—FTP上传下载

  不错的文章:http://www.cnblogs.com/greatverve/archive/2012/03/03/csharp-ftp.html

36910
来自专栏androidBlog

AsyncTask源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

7200
来自专栏androidBlog

AsyncTask 使用及封装实践

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/details/...

19310
来自专栏我和未来有约会

silverlight向服务器post数据类

using System; using System.Net; using System.Windows; using System.Windows.Co...

23750
来自专栏码匠的流水账

聊聊storm的IWaitStrategy

storm-2.0.0/storm-client/src/jvm/org/apache/storm/policy/IWaitStrategy.java

13650
来自专栏yl 成长笔记

web 上读取图片,并转化为指定格式

9710
来自专栏空帆船w

Android Handler 消息处理机制

日常开发中,一般不会在子线程中直接进行 UI 操作,大部分采取的办法是创建 Message 对象,然后借助 Handler 发送出去,再在 Handler 的 ...

23430
来自专栏aCloudDeveloper

AVL树探秘

一、AVL树   AVL树是一种平衡查找树,在前面的两篇文章:二叉搜索树 和 红黑树 中都提到过。由于二叉搜索树在某些特殊情况下是不平衡的(任意一个结点深度过大...

307100
来自专栏码匠的流水账

聊聊resilience4j的fallback

vavr-0.9.2-sources.jar!/io/vavr/control/Try.java

24510

扫码关注云+社区

领取腾讯云代金券