js 变量和数据类型

变量

JavaScript是弱类型的语言,变量是松散的。所谓松散是可以保存任何类型的变量。即声明不同数据类型的变量使用同一个关键字 var,变量就是变化的量,变量的作用就是用来装数据的容器。声明变量的时候不用考虑类型,但是处理和计算的时候要考虑类型.

定义变量

定义变量使用关键字 var 来定义变量名。

1
2
3
4
// 在全局作用域下声明了变量 a
var a;
// 使用赋值运算符来给变量赋值
a = "a此时是字符串";

赋值:

  • 赋值运算符为“=”,这个等号不用判断两者是否相同。
  • 如果判断是否相同,可使用==(===)。

以上两步可简写为:

1
var a = "a此时是字符串";

注意:

1
2
3
function foo(){
msg = "我是函数内部定义的全局变量";
}

上面例子省略了 var 操作符, msg 就变成了全局变量,函数外部也能访问到,但不要这样做!。

变量命名规范

  • 由字母、数字、下划线、$ 组成且开头不能是数字定义变量名。
  • 不能使用特殊符号或者特殊符号开头来定义变量名(_除外)。
  • 不能以关键字来定义变量名
  • 变量的名称要有实际意义
  • 规则中所说的字母包括ASCII和Unicode字母字符,如汉字,但不推荐使用
  • 变量的命名遵守驼峰命名法,首字母小写,第二个单词的首字母大写 例如:userName

关键字;

  • 不能使用保留字来定义变量名

关键字;

注意:在JS中,是严格区分大小写的。

执行环境和作用域

执行环境是 JavaScript 中最为重要的一个概念。定义了变量或函数有权访问其它数据。每个环境中都有一个与之关联的变量对象,我们编写的代码无法访问,但是环境中定义的变量存放在这个对象中。

全局执行环境是最外围的一个执行环境。根据 ECMAScript 实现所在的宿主环境的不同,表示执行环境的对象也不一样。在 web 浏览器中,全局执行环境被认为是 window 对象,因此所有的全局变量和函数都是作为 window 对象的属性和方法创建的。某个环境中的代码全部执行完,该环境中的变量被销毁,保存在其中的所有的变量和函数定义也随之销毁。全局执行环境直到应用程序退出才销毁。

每个函数都有自己的执行环境。当代码在一个环境中执行时,会创建作用域链。作用域链式保证对执行环境有权访问的所有变量和函数的有序访问。作用域的前端始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象作为变量对象。活动对象在最开始的时候只包含一个变量,即 arguments 对象。作用域中的下一个变量对象来说包含(外部的环境),而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境,全局执行环境的变量对象始终都是作用域链中的最后一个对象。

一个变量的作用域是程序源代码中定义这个变量的区域。全局变量拥有全局作用域,在 JavaScript 代码中任何地方都是有定义的。而在函数内部声明的变量只有在函数体内有定义,它们是局部变量,作用域是局部的。

在函数体内部,局部变量的优先级高于同名的全局变量。

函数作用域和声明提前

块级作用域是指在一对花括号内的代码都具有各自的作用域,而且变量在声明它们的代码之外是不可见的。但是 JavaScript 没有块级作用域的概念。而是使用了函数作用域。JavaScript 的函数作用域是指函数内声明的所有变量在函数体内始终是可见的。

1
2
3
4
5
6
7
8
9
10
11
function test(o){
var i = 0; // i 在整个函数体内部有定义
if (typeof o == 'object'){
var j = 0; // j 在函数体内有定义
for(var k = 0; k < 10; k++){ // k 在函数体内是有定义的,不仅仅是在循环内
console.log(k); // 输出 0~9
}
console.log(k); // 输出 10
}
console.log(j); // j 已经定义了,但是可能没有初始化
}

作为属性的变量

当声明一个变量时,实际上是定义了一个全局对象的一个属性,当使用 var 声明变量时,创建的这个对象是不可配置的,也就是说这个变量不能通过 delete 操作符来删除。如果在非严格模式下,给一个未声明的全局变量赋值的话, JavaScript 会自动创建一个全局变量。以这种方式创建的变量是全局对象的正常的可配置属性,并且可以删除它们。

作用域链

嵌套的函数体内部,可以访问它上一级作用域中的变量。

延长作用域链:

  • try-catch 语句
  • with 语句

垃圾收集

  • 标记清除
  • 引用计数
  • 性能问题
  • 管理内存

数据类型

javaScript 数据类型有两类: 基本数据类型 和 复杂数据类型,其中基本数据类型(简单类型)有: Number/String/Boolean/Uundefined/Null一种复杂数据类型:object:Array/Date/Math/RegExp/

typeof 操作符

  • “undefined” –> 这个值未定义
  • “boolean” –> 这个值是布尔值
  • “string” –> 这个只是字符串
  • “number” –> 这个值是数值
  • “object” –> 这个值是对象或null
  • “function” –> 这个值是函数

typeof 操作符号后面的操作数可以是变量,也可以是字面量;

typeof 误区:

  • null 值返回 “object”;
  • Safari5 以及之前的版本、Chrome7 以及之前的版本对正则表达式调用返回”object”,
  • 其他浏览器在这种情况下返回”object”
  • 未初始化的变量和没有定义的变量操作符 typeof 都返回 “undefined”, 但它们有本质区别

Nnumber 数字类型

字面量: var num = 数字;

包括正数,负数,小数

  • 取值范围:
    • 能表示的最大值是±1.7976931348623157乘以10的308次方
    • 能表示的最小值是±5 乘以10的-324次方
  • 表示方式
    • 十进制
    • 十六进制 以 0x 开头,从 0-9,a(A) 到 f(F)的范围。
    • 八进制 以 0 开头,0-7 组成。
  • NaN (not a number) 也是 number 类型,NaN 不等于自身
  • 两个都为字符串的变量相减,得到的是NaN.

  • 浮点数:

    • 计算浮点数时会丢失精度
    • 通常用整数的计算来表示浮点数的计算
    • 不要以两个浮点数是否相等作为条件判断的依据(判断范围还是可以的)

String,字符串类型

字面量: var str = “字符串”;

字符串的长度: str.length;

  • 凡是用””或者’’引起来的全是字符串类型。

转义字符:

  • \” 转双引号
  • \’ 转单引
  • \r 回车
  • \n 换行
  • \t 制表符
  • \f 进纸
  • \xnn 以十六进制表示一个字符(n 是 0~F)
  • \unnnn 以十六进制代码nnnn表示一个 Unicode 字符 (n 是 0~F)

字符串的特点

ECMAScript 中的字符串是不可变的,也就是说,字符串一旦创建,它们的直就不能改变。要改变某个变量保存的字符串,首先要销毁原来的字符串,然后再用另一个包含心智的字符串填充该变量。如:

1
2
var str = "Java";
str = str + "Script";

转换为字符串

数值、布尔值、对象和字符串值都有 toString() 方法, 但是 null 和 undefined 没用这个方法。

调用toString() 方法时,大多数情况下不传参数,但是如果传递了一个参数,输出数值的基数。默认情况下,toString() 方法以十进制格式返回数值字符串表示。而通过传递基数,可以输出对应的二进制、八进制、十六进制。

1
2
3
4
5
6
var n = 10;
console.log(n.toString()); // "10"
console.log(n.toString(2)); // "1010"
console.log(n.toString(8)); // "12"
console.log(n.toString(10)); // "10"
console.log(n.toString(16)); // "a"

在不知道要转换的值是什么类型的时候,可以用 String() 函数,它可以将任意类型转成字符串。

Boolean 布尔类型

  • 布尔数据类型两个数据值: true/false
  • 实际运算中,true 代表1, false代表0;

Undefined 表示声明但未赋值的变量

在 js 中,一下四种情况的返回值是 undefined

  • 变量声明了但没有赋值
  • 函数没有返回值默认返回undefined
  • 函数传递的实参个数少于形参个数时,未传递的参数值为undefined
  • 对象没有定义的属性默认为undefined

Null

typeof 判断时值为 object (值为空)/引用为空,内存里找不到这个变量。

再如:

1
console.log(undefined == null); // true 两等号判断,两边都转成false

总的来说,只要意在保存对象的变量还没有真正保存对象,就应该让该变量保存 null 值,这样做体现了 null 作为空对象指针的惯例,也区分了 undefined 和 null。


复杂类型(来自 JavaScript 高级程序设计)

  • object 对象

ECMAScript 中的对象就是一组数据和功能的集合。可以通过 new 操作符后跟要创建的对象类型的名称来创建。而创建 Object 类型的实例并为其添加属性或方法,就可以创建自定义对象,如:

1
var o = new Object();

Object 的每个实例具有的属性和方法

  • constructor: 保存着用于创建当前对象的函数,即构造函数。
  • hasOwnProperty(propertyName): 用于检查给定的属性在当前对象的实例中(而不是在原型中)存在;参数是字符串。
  • isPrototypeOf(object): 检查传入的对象是否是传入对象的原型。
  • propertyIsEnumerable(propertyName): 检查给定的属性是否能够使用 for-in 语言来枚举。参数是字符串。
  • toLocalString(): 返回对象的字符串表示,该字符串与执行环境的地区对应。
  • toString(): 返回对象的字符串表示。
  • valueOf(): 返回对象的字符串、数值、或布尔值表示。通常与 toString() 方法的返回值相同。

数据类型转换

隐式数据类型转换

变量参与到运算中,程序对变量进行的数据类型转换(不是程序员进行的数据类型)

强制数据类型转换

  • 将数字转换为字符串
    • String
    • 变量.toString ,注意:null 和 undefined 没有 toString() 方法
  • 将字符串转换为数字
    • Number
      • 转换后保留原数据,不会对数据进行四舍五入。
      • 非数字类型字符串转换后,比如 undefined,得到 NaN 。
      • 如果字符串中包含有效的十六进制格式,则将其转换为相同大小的十进制整数值。
    • parseInt
      • 对小数转换后保留的是整数部分,不会对数据进行四舍五入。
      • 如果是数字后边有非数字字符串,转换后得到的是前边数字的整数部分。
    • parseFloat
      • 转换为数字类型之后保留原数据,不进行四舍五入。
      • 非数字类型字符串转换后,得到 NaN 。
      • 如果是数字后边有非数字字符串,转换后得到的是前边数字的部分。
  • 将其他类型转换为布尔类型:所有类型的值都可以转化成布尔值
    • Boolean
    • 会转化成false的值有:
      • 空字符串
      • 数值零
      • NaN
      • undefined
      • null

假值:空字符串””/数字0/null/undefined/false/NaN


基本数据类型和复杂类型总结

  • 基本类型—值类型— String Undefined Number Boolean Null
  • 复杂类型—引用类型– Object 数组–Array,Date….

  • 基本类型的值存储在—- 栈中

  • 复杂类型的地址(引用)存储在栈中,—地址指向的空间中的对象(对象)—对象存储在堆中

    • 创建对象并返回对象—返回的是对象的地址(对象在堆空间中的地址)
  • 基本类型传值的时候,传递的是值

  • 复杂类型(引用类型)传递的时候,传递的是:地址(引用)
感谢您的支持!