此题是看到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:
再来几个例子:
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