1, 基本类型和引用类型的值
ECMAscript 的变量和其他语言变量有所不同, 其为松散型变量, 每个变量只是一个占位符而已. 变量可能包含两种类型的值,
一种为基本类型的值, 在内存中占据固定大小, 保存在栈内存中, 简单的数据段, string,number,Boolean,null,undefined,
一种为引用类型的值, 指可能为多个值构成的对象, object, 保存在堆内存中; 引用类型的值保存在内存中的对象, js 不允许直接操控内存中的对象. 实际操控对象的引用来操控对象, 其变量是个指向该对象的指针.
1.1 动态的属性
当操作变量时候, 对于引用类型的值, 可以添加属性, 方法, 可以改变, 删除属性和方法; 但是对于基本类型的值, 就不可以添加属性(虽然不会产生错误)
// 基本类型的值
var name = "double";
name.age = 27;
name.sex = "man";
console.log(name.age) //undefined
// 引用类型的值
var person = new Object();
person.name = "double";
person.age = 20;
person.sex = "man"console.log(person.name) //double
1.2 复制变量的值
对于基本类型来说, 复制变量值就是 clone 了, 两个变量完全独立, 没有任何关系
对于引用类型来说, 复制变量值实际复制的只是个指针, 指向存储在堆中的一个对象, 两个变量实际将引用同一个对象改变任意一个, 都将改变
// 对于基本类型, 复制之后完全独立, 没有关系
var one=12;
var two=one;
one=13;
console.log(one) //13
console.log(two) //12
// 对于引用类型, 变量名只是指针, 引用的是同一个对象
var obj1=new Object();
var obj2=obj1;
obj1.name="double";
obj1.sex="man";
obj2.sex="woman";
console.log(obj2.name) //double
console.log(obj1.sex) //woman
1.3 传递参数 js 中所有函数参数都是按值传递的.
把函数外部的数复制给参数, 基本类型的传递如同基本变量的复制一样, 而引用类型的传递如同引用变量的复制一样. 但是参数是按值传递的.
在传递基本类型值时, 被传递的值复制给局部变量(也就是命名参数), 仅仅是值得修改. 在传递引用类型值时, 将这个值再内存中的地址复制给局部变量, 因此这个局部变量的变化会反映在函数的外部.
function add(num) {
num += 10;
return num;
}
var count = 20;
var result = add(count) console.log(count) //20
console.log(result) //30
function setName(obj) {
obj.name = "double"; // 函数的内部, obj 和 person 引用的是同一对象, 即使参数是按值传递的
obj = new Object(); // 即使函数内部被修改, 但是原有的引用未改变, 重写 obj 时, 变量的引用只是局部变量, 函数执行完毕立刻被销毁
obj.name = "single";
}
var person = new Object();
setName(person);
console.log(person.name); //double
1.4 检测类型
检测基本数据类型时, 一般用操作符 typeof, 但是当类型为 null 和对象时, 检测的都是 object; 检测引用类型, 想知道某个类型的对象用 instanceof 操作符.
var person=new Object();
var colors=[];
var pattern=/d/;
console.log(person instanceof Object) // 都是 true
console.log(colors instanceof Array)
console.log(pattern instanceof RegExp)
当 instanceof 检测引用类型和 Object 构造函数时, 始终会返回 true; 而检测基本数据类型则为 false
2, 执行环境和作用域
执行环境 (execution context) 定义了变量或者函数有权访问的其他数据, 定义了它们各自的行为. 每个环境中都有一个与之相关的变量对象, 环境中定义的所有变量和函数都保存在这个对象中, 全局执行环境是最外围的执行环境, 即 window 对象. 某个执行环境中所有代码执行完毕后, 该环境被销毁.
执行环境有全局环境和函数环境两种
当代码在一个环境中执行, 会创建变量对象的一个作用域链, 以保证对执行环境有权访问的所有变量和函数的有序访问.
var color = "blue";
function change() {
var anotherColor = "red";
function changeAgain() {
var tempColor = anotherColor;
anotherColor = color;
color = tempColor;
console.log(tempColor) //red
console.log(anotherColor) //blue
console.log(color) //red
}
// console.log(tempColor) 访问不到
console.log(anotherColor) //red
console.log(color) //blue
changeAgain()
}
// console.log(tempColor) 访问不到
// console.log(anotherColor) 访问不到
console.log(color) //blue
change()
内部环境可以通过作用域链访问所有的外部环境, 而外部环境不能访问内部环境的任何变量和函数
2.1 延长作用域链
有些语句可以在作用域链的前端临时加个变量对象, 代码执行后就移除,
try-catch 语句中的 catch 块; with 语句.
2.2 没有块级作用域
js 中是没有块级作用域的, 所以 if 内的变量就是 window 对象下的; for 循环的变量同是,
if(true){
var color="red";
}
console.log(color) //red
for(var i=0;i<10;i++){
console.log(i) //0-9
}
console.log(i) //10
声明变量
涉及到 var 操作符, 有 var 声明则是局部变量, 没有则是全局变量, 在函数的执行环境内, 外部是访问不到的 .
查询标识符
在某个环境中引用一个标识符, 必须通过搜索来确认该标识符代表着什么, 先从自身环境搜索, 然后沿着作用域链向上溯回查询, 一旦找到就 OK.
var color="red";
function getColor(){
return color
}
console.log(getColor()) //red
基础不牢, 地动山摇
来源: https://www.cnblogs.com/iDouble/p/8372310.html