1.**ECMAScript中的所有参数传递的都是值,不可能通过引用传递参数。**
2.**五种基本数据类型是按值访问的**,因为可以操作保存在变量中的实际值。引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用而不是实际的对象。因此,**引用类型的值是按引用访问的。(实际上这种说法并不严密,当复制保存着对象的某个变量时,操作的是对象的引用。但在为对象添加属性是,操作的是实际的对象。)**
3.对于引用类型的值,我们可以为其添加属性和方法,也可以改变和删除其属性和方法。但是,我们不能给基本类型的值添加属性,尽管这样做不会抛出错误。这说明只能给引用类型动态地添加属性,以便将来使用。
4.复制引用操作时,复制操作结束后,两个变量实际上将引用同一个对象。因此,改变其中一个变量,就会影响另一个变量。
5.**ECMAScript中所有参数都是按值传递的。当我们给函数传入参数时,实际就是把函数外部的值复制给函数内部的参数,这和把值从一个变量复制到另一个变量一样。**
为了说明函数的参数是按值传递的,请看下面的例子:
~~~
function setName(obj) {
//相当于省略了var obj = person;
obj.name = ‘Nicholas’;
obj = new Object(); //重写了obj的值,这时候obj与person引用的对象无关了。
obj.name = ‘Greg’;
}
var person = new Object();
setName(person);
alert(person.name); //‘Nicholas’
~~~
**个人理解:如果参数是按引用传递的话,那么obj和person应该始终指向同一个对象,实际上把person传入到setName中只不过是把person指向的对象的指针副本复制给obj。给ECMAScript函数传变量,相当于把外部变量赋值给函数内的局部变量。**
另一个面试中常见的陷阱:
~~~
var foo = {
bar: function(){return this.baz;},
baz: 1};
(function(){return typeof arguments[0]();})(foo.bar); //undefined
~~~
相当于arguments[0] = function(){return this.baz;}
6.***instanceof操作符用于检测变量的具体引用类型***。如果变量是给定引用类型的实例,则返回true。
语法:result = variable instanceof constructor;
7.在Web浏览器中,全局执行环境被认为是window对象,因此所有全局变量和函数都是作为window对象的属性和方法创造的。**某个执行环境中的所有代码执行完毕后,该环境被销毁,保存在其中的所有变量和函数定义也随之销毁**(全局执行环境直到应用程序退出--例如关闭网页或浏览器--时才会被销毁)。
8.延长作用域链的方法有两个:
--try-catch语句的catch块
--with语句
这两个语句都会在作用域链的前端添加一个变量对象。对with语句来说,会将指定对象添加到作用域链中。对catch语句来说,会创建一个新的变量对象,其中包含的是被抛出的错误对象的声明。
9.JavaScript中没有块级作用域,因此if语句中的变量声明会添加到当前的执行环境中。在使用for语句时尤其要牢记这一差异,例如:
~~~
for (var i=0; i <10; i++) {
doSomething(i)
}
alert(i); // 10
~~~
10.***优化内存占用的最佳方式,就是为执行中的代码只保留必要的数据。一旦全局对象、全局对象属性以及循环引用变量的引用不再有用,最好通过将其值设置为null来释放其引用--这个做法叫做解除引用。这一做法适用于大多数全局变量和全局对象的属性***。如下面这个例子所示:
~~~
function creatPerson(name) {
var localPerson = new Object();
localPerson.name = name;
return localPerson;
}
var globalPerson = creatPerson(‘Ken’);
globalPerson = null; //在不使用它的时候手工为它解除引用。
~~~
11.基本类型值在内存中占据固定空间大小,因此被保存在栈内存中;引用类型的值是对象,保存在堆内存中。