网页设计实战之JavaScript(1) --变量与数据类型

一、JavaScript之变量

1、变量定义

定义变量是通过var关键字来定义一个变量,若变量不通过var定义,则视为全局变量。

(1)变量声明

  • 一般声明方式
var name;//变量声明
var age;//变量声明
var add;//变量声明
  • 同一行可以声明若干变量,变量之间用逗号分开。
var name="AFADF",age=23,add=false;

变量名的规则:

  • 大小写敏感,name 和 Name不是同一个变量。
  • 变量名中不能包括特殊字符,如:减号,加号等,
  • 变量名不能数字字母开头。
  • 字母以驼峰形式便于阅读,如:myName,yourAge
  • 变量名以确定含义的单词,反映业务的内容。如:a,b,c这种变量名,难以理解它表示的含义。
  • 同名的变量声明,会覆盖前一个声明的变量,原来的值会消失。
var name ="hello";
var name = "world";

(2)变量的初始化

变量在使用前需要初始化,给它一个值。
变量声明时未初始化,那么它的值是undefined,什么也不是。既不是字符串,也不是数值,也不是对像。

  • 在声明时初始化
var name="朱元璋"; //变量声明时初始化
var age=78;      //变量声明时初始化
  • 在程序中初始化:
var name; //变量声明时无值,undefined
name="朱元璋"; //初始化

2、变量种类

若按照变量作用域和变量生命周期来划分,可将变量分为全局变量和局部变量。

(1) 全局变量

从作用域角度,全局变量位于作用域链的最顶端;从变量生命周期角度,全局变量生存期为整个程序生命周期,即直到程序结束,全局变量才销毁。

var address = "北京";//全局变量
 function GetUserInfo() {
	var userName = "小王";//userName局部变量
 	return userName +"-"+ address;
}
console.log(GetUserInfo());//小王-北京
console.log(address);//北京

(2) 局部变量

从作用域角度,局部变量位于特定的局部域,如特定的函数内部;从变量生命周期角度,局部变量声明周期只在其所处的特定作用域内,超出该作用域,就失效。如函数变量,直在函数内部有效。

function GetUserInfo() {
       var userName = "我是小王";
       return userName;
    }
console.log(GetUserInfo());//我是小王
console.log(userName);//报错:userName is not defined

3、变量链式作用域

JS中的变量作用域是通过this指针,从当前的作用域开始,从当前作用域由内向外查找,直到找到位置,这里分为几个逻辑:

  • .从当前作用域由内向外查找,若找到,就停止查找,否则,继续查找,直到查到window全局作用域为止,若任然未找到,则会出错,提示该变量未定义;

  • 当内部作用域变量名与外部作用域变量名相同时,内部作用域的覆盖外部作用域。

var dateTime='2018-09-16';
function GetUserInfo(){
    var age=120;
    var name="中国";
    function printme(){
       var name="hello";
       var address="中国";   
       //中国-拳王-2018-06-05              
       console.log(address+"-"+name+
        "-"+age+"-"+dateTime);
     }
    return printme();
 }
GetUserInfo();//中国-hello-2018-09-16

作用域有三层:全局,GetUserInfo()函数内,printme()函数内。在printme()函数中,在调用log()函数时,name变量用本作用域中的name(=“hello”),age在本域中无此变量,则用外层的age变量,dateTime变量在本域中和外层域中都没有这个变量,在再外层的外层中去查找。

4、注意

(1)、非规范化定义全局变量

定义全局变量的另一种方式,就是不使用关键字var

function GlobalParam() {
         userName = "hello";// 在函数中定义一个全局变量
 }
  GlobalParam();
 console.log(userName);//hello

(2)、js中没有块作用域

var maxNum = 100;
for (var i = 0; i < maxNum; i++) {
        var sum = 0;// 这个变量,在外层是可以访问到的
       sum = sum + i;
}
console.log(sum);//99。因为JavaScript没有块级作用域,因此能在for语句外部访问变量sum

{
	var test = "hello";
}
console.log(test ); // "hello", 在C++和C#等开发语言不同。

5、变量的存储和回收

(1) 变量的存储

js中的变量虽然不区分类型,但是实际上Ecmascript包含两种类型,基本类型和引用类型.

基本类型有5种:Undefined,Null,Boolean,Number,String,基本类型是按值访问的,因为可以操作保存在变量中的实际的值。

引用类型的值是保存在内存中的对象。与其他语言不同,JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。在操作对象时,实际上是在操作对象的引用(也称为句柄)而不是实际的对象.

(2)回收机制

每个对象中都有一个引用次数,跟踪记录每个值被引用的次数。当声明了一个变量并将一个引用类型值赋给该变量时,则这个值的引用次数就是1。如果同一个值又被赋给另一个变量,则该值的引用次数加1。相反,如果包含对这个值引用的变量又取得了另外一个值,则这个值的引用次数减 1。当这个值的引用次数变成 0 时,则说明没有办法再访问这个值了,因而就可以将其占用的内存空间回收回来。这样,当垃圾收集器下次再运行时,它就会释放那些引用次数为零的值所占用的内存。

垃圾收集器在运行的时候会给存储在内存中的所有变量都加上标记。然后,它会去掉环境中的变量以及被环境中的变量引用的变量的标记。而在此之后再被加上标记的变量将被视为准备删除的变量,原因是环境中的变量已经无法访问到这些变量了。最后,垃圾收集器完成内存清除工作,销毁那些带标记的值并回收它们所占用的内存空间。

(3)、内存泄漏

  • 全局变量引起的内存泄漏
function mem_leaks(){  
    leak_str = 'xxxxxx';//leak_str 成为一个全局变量,不会被回收
}
  • 闭包引起的内存泄漏
var leaks = (function(){  
    var leak = 'xxxxxx';// 被闭包所引用,不会被回收
    return function(){
        console.log(leak);
    }
})()

二、数据类型

1、基本数据类型

  • 布尔值(Boolean):有2个值分别是:true 和 false.
  • null : 一个表明 null 值的特殊关键字。 JavaScript 是大小写敏感的,因此 null 与 Null、NULL或变体完全不同。
  • undefined :和 null 一样是一个特殊的关键字,undefined 表示变量未定义时的属性。
  • 数值(Number):整数或浮点数,例如: 42 或者 3.14159。
  • 字符串(String):字符串是一串表示文本值的字符序列,例如:“Howdy” 。
  • 代表(Symbol) ( 在 ECMAScript 6 中新添加的类型).。一种实例是唯一且不可改变的数据类型。

2、对象(Object)

对象是组成类型,一个对象是多个原始类型的值的集合,可以看作是一个存放各种值的容器。对象是最复杂的数据类型,又可以分成三个子类型:
狭义的对象(object)
数组(array)
函数(function)
狭义的对象和数组是两种不同的数据组合方式,除非特别声明,一般而言“对象”都特指狭义的对象。函数其实是处理数据的方法,JavaScript 把它当成一种数据类型,可以赋值给变量,这为编程带来了很大的灵活性,也为 JavaScript 的“函数式编程”奠定了基础。

(1)、Number.NaN 属性

NaN 属性是代表非数字值的特殊值。该属性用于指示某个值不是数字。可以把 Number 对象设置为该值,来指示其不是数字值。
使用 isNaN() 来判断一个值是否是数字。原因是 NaN 与所有值都不相等,包括它自己。
isNaN() 函数可用于判断其参数是否是 NaN,该值表示一个非法的数字(比如被 0 除后得到的结果)。

console.log(typeof Number.NaN === 'number'); // true

(2)、特殊的null

null的类型,使用typeof时返回的是object,只把它当作object的一种特殊值。

不同的对象在底层都表示为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,null 的二进制表示是全 0,自然前三位也是 0,所以执行 typeof 时会返回“object”。

console.log(typeof null);// object

(3)、null与undefined

都可以表示“没有”,含义非常相似。将一个变量赋值为undefined或null,老实说,语法效果几乎没区别。实际的区别是:null是一个表示“空”的对象,转为数值时为0;undefined是一个表示"此处无定义"的原始值,转为数值时为NaN。

注意:
JavaScript 预期某个位置应该是布尔值,会将该位置上现有的值自动转为布尔值。转换规则是:

  • 除了下面六个值被转为false,其他值都视为true。undefined;null;false;0;NaN;""或’’(空字符串)。
  • 空数组([])和空对象({})对应的布尔值,都是true。

3、字面量(常量)

字面量是由语法表达式定义的常量;或通过由一定字词组成的语词表达式定义的常量。

  • 数组字面量
    数组字面值是一个封闭在方括号对([])中的包含有零个或多个表达式的列表,其中每个表达式代表数组的一个元素。当你使用数组字面值创建一个数组时,该数组将会以指定的值作为其元素进行初始化,而其长度被设定为元素的个数。
var arr = ["a", "b", "c"];
var a=[3];

  • 布尔字面量
    true和false。
    不要混淆作为布尔对象的真和假与布尔类型的原始值true和false。布尔对象是原始布尔数据类型的一个包装器。

  • 整数字面量

整数可以用十进制(基数为10)、十六进制(基数为16)、八进制(基数为8)以及二进制(基数为2)表示。
十六进制整数以0x(或0X)开头,可以包含数字(0-9)和字母 a~f 或 A~F。

0, 117, -345 (十进制, 基数为10)
015, 0001, -0o77 (八进制, 基数为8) 
0x1123, 0x00111,  -0xF1A7 (十六进制, 基数为16"hex")
0b11, 0b0011,  -0b11 (二进制, 基数为2)
  • 浮点数字面量
    浮点数字面值可以有以下的组成部分:

一个十进制整数,可以带正负号(即前缀“+”或“ - ”),
小数点(“.”),
小数部分(由一串十进制数表示),
指数部分。
指数部分以“e”或“E”开头,后面跟着一个整数,可以有正负号(即前缀“+”或“-”)。浮点数字面量至少有一位数字,而且必须带小数点或者“e”(大写“E”也可)。
简言之,其语法是:
[(+|-)][digits][.digits][(E|e)[(+|-)]digits]

3.14      
-.2345789 // -0.23456789
-3.12e+12  // -3.12*1012
.1e-23    // 0.1*10-23=10-24=1e-24
  • 对象字面量
    对象字面值是封闭在花括号对({})中的一个对象的零个或多个"属性名-值"对的(元素)列表。你不能在一条语句的开头就使用对象字面值,这将导致错误或产生超出预料的行为, 因为此时左花括号({)会被认为是一个语句块的起始符号。

  • RegExp 字面值
    一个正则表达式是字符被斜线(译注:正斜杠“/”)围成的表达式。

var re = /ab+c/;
  • 字符串字面量
    字符串字面量是由双引号(")对或单引号(’)括起来的零个或多个字符。字符串被限定在同种引号之间;也即,必须是成对单引号或成对双引号。
""
''
"adfadf"
'12312'
"123564564"

4、类型转换

javaScript是一种动态类型语言,声明变量时可以不必指定数据类型,而数据类型会在代码执行时会根据需要自动转换。

在包含的数字和字符串的表达式中使用加法运算符(+),JavaScript 会把数字转换成字符串。

var a = "1234"+56; // 123456

在涉及其它运算符(减号’-’)时,JavaScript语言不会把数字变为字符串。

var a = "100" - 10// 90
var a = "10" * 10// 100
var a = "10" / 2// 5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章