变量

1. 变量的声明
通过关键字 var 来声明一个变量. 变量的英文是 variable quantity. 可以单纯只声明一个变量, 也可在声明变量的同时对它进行赋值. var x; var x = 10;

2. 变量的类型
JavaScript 支持这些类型: 空值 (null, undefined), 数字, 布尔值 Boolean (true, false), 字符串 String, 数组 Array, 对象 Object, ES6 又有了 Symbol. var w = 1, h = 1; // 整形数字 Line 45575 var EPS = 0.00001; // 浮点数 Line 26715 var msg = "THREE.Matrix4: .getInverse() can't invert matrix, determinant is 0"; // 字符串 Line 1530 var hasMaterial = true; // 布尔值: 真 Line 10033 var hasFaceUv = false; // 布尔值: 假 Line 10034 var context = null; // 空值 Line 7495 var materialIndex = undefined; // 未定义 Line 10898 var array = []; // 数组 Line 11673 var positions = [ 1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, -1 ]; // 数组 Line 45752 var hsl = {}; // 对象 Line 6870 var data = { // 对象 Line 9984 metadata: { version: 4.5, type: 'Geometry', generator: 'Geometry.toJSON' } };

数组中包含对象, 对象中包含数组, 对象中的相邻的项用逗号","隔开, 最后一项的后面不带任何符号 var points = [ {x:0, y:0}, {x:1, y:1} ]; var data = { book_names: ['JS', 'JAVA', 'C++'], book_price: [66, 68, 88] }

3. JavaScript 有两种空值: null, undefined
若用运算符 "==" 来作判断, 则会判断为相等, 需要使用严格相等运算符 "===" 来区分. null 表示程序级的, 意料之中的值的空缺, 一般在赋值时、或作为参数传入函数时使用. 对它执行 typeof 预算, 返回字符串 "object". var a = null; console.log( typeof(a) ); // object this.renderBufferDirect = function ( camera, fog, geometry, material, object, group ) { ... ... } _renderer.renderBufferDirect( shadowCamera, null, geometry, depthMaterial, object, null ); 而 undefined 是更深层次的空值, 它表明变量未被赋值, 也即未定义. 注: 申明一个变量并且赋值为 null 与未作任何赋值, 用 "===" 和 typeof 判断时是不一样的. var a; console.log( a == null ); // true console.log( a === null ); // false console.log( a == undefined ); // true console.log( a === undefined ); // true console.log( a ); // undefined console.log( typeof(a) ); // undefined

4. 原始值和包装对象: 上面的赋值全都是原始值;
通过 new + String(), Number(), Boolean() 构造函数的方式来显式创建的是包装对象. 它们与原始值不完成相等, 用"==="和typeof可查看.
用引号""/''引起来的就是一个字符串值, JavaScript 会通过调用 new String() 的方式来转换成对象, 这个对象继承了字符串的方法, 可 一旦引用结束, 这个新创建的对象就会立即销毁. 如下面的 str.len = 4 打印出来是undefined, 但 str2.len 的值却可以保留. var str = 'WebGL', n = 1, b = true; var str2 = new String( 'WebGL' ), n2 = new Number( 1 ), b2 = new Boolean( true ); str.len = 4; str2.len = 6; console.log( str == str2 ); // true console.log( n == n2 ); // true console.log( b == b2 ); // true console.log( str === str2 ); // false console.log( n === n2 ); // false console.log( b === b2 ); // false console.log( str.len ); // undefined console.log( str2.len ); // 6

5. 和对象的区别:
运行以下代码, 你会发现即使应用 "==" 运算符来做检测, 依然得到 false. 因为那是两个不一样的 Object, 在内存中有两个不同的存放位置, 而变量是没有的. 变量存放在栈, 用它来指引对象. var str = new String( 'WebGL' ); // 不同 str = 'WebGL' var str2 = new String( 'WebGL' ); console.log( str == str2 ); // false console.log( str === str2 ); // false

6. 变量的作用域: 一个变量的作用域scope是在程序中定义这个变量的区域.
(1) 全局变量: 定义在顶层函数 function( ){ } 的外部, 在整个代码区域都可用;
(2) 局部变量: 在函数内部声明的变量, 只在函数体内有定义.
当有同名的全局变量和局部变量时, 在函数体内, 局部变量的优先级高, 局部变量的值覆盖了全局变量. var scope = 'global'; function checkScope(){ var scope = 'local'; return scope; } checkScope(); // 'local' 如在函数体内定义的变量没加var, 则默认该变量是全局变量. function checkScope2(){ scope = 'local'; } checkScope2(); console.log( scope ); // 'local' 根据函数的作用域声明提前, 和局部变量的值覆盖了全局变量, 以下代码的第1个 scope 就取局部变量的值, 但由于没有执行到 var 语句, 因此还未被赋值, 所有输出是 undefined. var scope = 'global'; function checkScope3(){ console.log( scope ); // undefined var scope = 'local'; console.log( scope ); // 'local' } checkScope3(); 在Three.js代码以下中, vertexColors 和 vertexNormals 都是局部变量. function addFace( a, b, c, materialIndex ) { var vertexColors = ( colors === undefined ) ? [] : [ scope.colors[ a ].clone(), scope.colors[ b ].clone(), scope.colors[ c ].clone() ]; var vertexNormals = ( normals === undefined ) ? [] : [ new Vector3().fromArray( normals, a * 3 ), new Vector3().fromArray( normals, b * 3 ), new Vector3().fromArray( normals, c * 3 ) ]; } 变量scope在addFace()的外部定义, 即在外层函数定义, 内层函数可访问外层函数定义的变量, 这是闭包.

在 ES6 中,推荐使用 let、const.