1 变量作用域和作用域链
作用域:指的是变量和函数的访问范围,也就是说作用域控制着变量的可见性和生命周期,包括局部作用那个与和全局作用域;
局部作用域:指的是一般只在固定代码片内可以访问的作用域,常见的在函数内部定义的变量或函数;
全局作用域:指的是在代码任何地方都可以访问的变量或对象。
例如在下面函数中,alert(a1)首先在fun2函数区域寻找有定义的a1变量,如果有,就使用fun2函数中定义的变量a1,如果没找到,就继续一层一层向父级函数找,在fun1中找到了,就使用fun1中定义的变量a1。
<span style="white-space:pre"> </span>var a1 = 12; function fun1(){ var a2 = "ab"; function fun2(){ var s3 = 100; alert(a1); } fun2();//调用函数 } fun1();//调用函数
作用域链:在JS中当查询一个变量x时,首先会查找作用域链的第一个对象,如果在第一个对象中没有找到变量x的定义,就会依次向上一个(父级)对象中取查找。
在上述代码中,作用域链依次是fun1,fun2,window.
注意:在javascript中,直接定义的变量,就是全局的window
全局作用域分为以下几种情形:
1)函数内部,局部变量的优先级比同名的全局变量优先级高
var a4 = 123; function fun3(){ var a4 = 10000;//该变量的优先级要比同名的全局变量a4的优先级要高 alert(a4); } fun3();
2)在JS中没有块级作用域
var a5 = "string"; if (true){ var a6 = 123; for(var a7 = 1;a7 < 4;a7 ++){ console.log("123"); } }
以上代码中,a5,a6,a7作用域都是一样的,都是作用于window下的全局变量
3)最外层函数中声明的变量在本函数以及子函数都可以访问得到
<span style="white-space:pre"> </span>function fun4(){ <span style="white-space:pre"> </span> var a9 = "w"; <span style="white-space:pre"> </span> function fun5(){ <span style="white-space:pre"> </span> var a10 = 11; <span style="white-space:pre"> </span> a9 = "string"; <span style="white-space:pre"> </span> alert(a9); <span style="white-space:pre"> </span> } <span style="white-space:pre"> </span> fun5(); <span style="white-space:pre"> </span> var a11 = a10 + 1; <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>fun4();
局部变量的优先级高于全局变量,所以输出a9值为string,当在fun4()中调用a10时会显示a10没有定义,说明a10仅对当前函数可见,对父级函数是不可见的。
4)未使用var关键字定义的变量是全局变量
<span style="white-space:pre"> </span>function fun6(){ <span style="white-space:pre"> </span>a10 = 123;//声明了全局变量a10并赋值 <span style="white-space:pre"> </span>} <span style="white-space:pre"> </span>alert(a10);//可以访问变量a10
注意:JS官方规定可以未使用的var关键字直接定义变量,但是浏览器解析时报错,所以禁止这种方式定义全局变量.
5)全局变量都是window对象属性
<span style="white-space:pre"> </span>var a11 = 1000; <span style="white-space:pre"> </span>alert(a11);//1000
等价于
<span style="white-space:pre"> </span>var a11 = 1000; alert(window.all);
6) 作用域链的问题
<span style="white-space:pre"> </span>var a12 = 12; function fun7(){ alert(a12);//undefined var a12 = 1000; } fun7();//调用
若把var a12 = 1000;换成a12 = 1000;其输出结果为
第一种情况解释:变量a12首先在fun7()中寻找有没有定义的a12变量,找到了但是在函数输出之后,所以会返回一个undefined的值;
第二种情况解释:变量a12首先在fun7()中寻找有没有定义的a12变量,没有定义的a1变量,就向父级找,找到了定义了的var
a12 = 12变量,使用这个函数里面定义的变量。
2 对象的定义与使用
2.1 对象的定义
所谓对象就是一种无序的数据集合,由若干个键值对(属性-值)构成
2.2 对象定义的方式
<span style="white-space:pre"> </span>var a = {} //特点:书写简洁,常用来创建对象 var b = new Object() var c = Object.create(null) //通过构造函数创造对象实例
2.3 对象的键名
1)符合规范的对象键名都是字符串,加不加””和’’都可以
<span style="white-space:pre"> </span>var obj = { "p":"hello world" }; var obj1 = { p:"hello world" }; alert(obj.p+"\n"+obj1.p);
2)如果键名不符合标示符的条件(如第一个字符为数字或者含有恐吓或运算符等),则必须加上双引号或单引号,否则会出错
<span style="white-space:pre"> </span>var obj2 = { 1p:"hellow world"; };
var obj2 = { 1p:"hellow world"; 1+p:"hellow world"; };
2.4 对象的引用
不同变量名指向了同一个对象,那么他们都是这个对象的引用,也就是他们都是这个对象的引用,也就是他们共同指向了同一块内存区域,修改其中的一个变量的值,都会改变其他变量的值
<span style="white-space:pre"> </span>var obj3 = {}; var obj4 = obj3; obj4.str = "123"; alert(obj3.str);
2.5 表达式跟语句的判断
例如代码
{name:"zhangsan"}
1)如果像上面写法,JS是无法判断这个到底是表达式,还是语句(代码块),产生歧义
2)如果该代码出现在首行,也就是首行是{},一律解释为语句(代码块)
3)如果要解释为表达式(对象),则必须加上圆括号 ({name:"zhangsan"})
2.6 对象的属性
1)通过(.)读取对象属性值
<span style="white-space:pre"> </span>var obj5 = { name:"张三" }; alert(obj5.name);
2)通过下标读取属性的值
<span style="white-space:pre"> </span>var obj5 = { name:"张三" }; alert(obj5["name"]);
注意:
读取的属性如果是字符串类一定要加""或‘‘,否则报错;
读取的属性如果是数字可加可不加
3)对象的属性赋值
<span style="white-space:pre"> </span>var obj6 = { a:"name" }; obj6.a = "zhangsan"; obj6['a'] = "zhangsan";//或者
4)对象的属性查看.使用object.keys方法获取
<span style="white-space:pre"> </span>var obj7 = { name:"zhangsan", age:23, sex:"男", weight:"50KG" }; var keys = Object.keys(obj7); console.log(keys);
也可以采用in属性方法获取obj7的值
<span style="white-space:pre"> </span>for(var i in obj7){ alert(i);//打印的是对象中的属性(key) alert(obj7[i]);//打印的是属性值(value) }
3 字符串及字符串方法
3.1 字符串定义
字符串就是将0个或多个排在一起的字符,放在单引号或双引号之间,单个字母、单个数组或单个符号都可以称之为字符串
1)单引号里面可以嵌套双引号,但是不可以嵌套单引号;双引号里面可以嵌套单引号,但是不可以嵌套双引号
2)字符串连接
可以使用\将不在同一行的的字符串连接成一行
<span style="white-space:pre"> </span>var str7 = "helloworld helloworld\" "helloworld helloworld\" "helloworld helloworld";
也可以使用字符+将多个字符串链接成一行
<span style="white-space:pre"> </span>var str7 = "helloworld helloworld" +"helloworld helloworld" +"helloworld helloworld";
3.2 转义字符
1)包括:
\0 null
\b 后退键
\f 换页符
\n 换行符
\r 回车
\t 制表符
\v 垂直制表符
\‘ 输出单引号
\" 输出双银行
\ 连接符
转义字符为单独一个字符,在字符串中占一个长度
2)反斜杠的使用
\HHH 反斜杠后面跟3个八进制位(000--377);
var str8 = ‘\251‘;
\xHH 反斜杠后面跟2个十六进制位(00--FF);
var str9 = ‘\xFF‘;
\uXXX 反斜杠后面跟4哥16进制位(0000---FFFF);
var str10 = ‘\u0001‘;//常见于unload编码格式
注意:
1.在计算字符串长度时,上面的三种情况,也是当做一个字符参与字符串长度计算
2.算字符串长度,其实是计算的字符串字符的个数
3.所有转义字符只对控制台打印起作用.
3.3 字符串与数组
1)字符串可以视为字符数组,因此可以通过数组的下标形式来访问字符串中的字符(下标从0开始)
var str10 = "hello world";
alert(str10[6]);//值:w
2)字符串毕竟不是数组,无法通过下标形式来改变字符串中的某个字符
str10[6] = ‘H‘;//错误,无法修改
3)字符串的length属性不可设置
strll.length = 2;//错误
3.4 字符集
1)Javascript使用的是Unicode字符集,也就是在javascript内部,所有的字符都是用Unicode表示
2)Javascript不仅能用Unicode储存字符,还允许程序中使用Unicode来表示字符,
3)形式;/uXXXXX;其中XXXX表示Unicode编码,例如"\uFFFF";
4 字符串方法
4.1 字符串创建
1)自变量创建
var str1 = "hello world";
2)构造函数创建字符串对象
var str2 = new String("hello world");
4.2 string.fromCharCode()方法
该方法中的参数是一系列Unicode的码点(例如:‘\u0012‘
码点:0012),返回对应的字符串,
传入参数的值不能超过0xFFFF大小,
该方法定义在对象本身,而不是创建对象实例方法上面
var str = String.fromCharCode(0x12,0x45,0x67,0x122,0xfe);
alert(str);
注意:String.fromCharCode
而不是str.fromCharCode
4.3作用于实例对象的方法和属性
1)length 返回字符串的长度
2)charAt() 返回指定位置的字符,参数从0开始
<span style="white-space:pre"> </span>var str1 = "hello"; var res1 = str1.charAt(1);//res1 = e console.log("res1="+res1);
注意,该方法等效于用数组下标方式返回字符,但是如果参数为负数或者超过字符串长度,charAt将返回空字符串
4.4 charCodeAt()方法
该函数返回给定位置字符Unicode的码点(10进制表示),刚好是String.fromCharCode()的逆操作
<span style="white-space:pre"> </span>var str2 = "acd"; var res3 = str2.charCodeAt(2);u alert(res3);//100
逆操作:
<span style="white-space:pre"> </span>var resu3 = String.fromCharCode(100);//把100转化为Unicode字符d alert(res3);
4.5 concat方法
concat中参数可以写多个字符串
<span style="white-space:pre"> </span>var str3 = "hello"; var str4 = "world"; var str5 = "zhang"; var str6 = "san"; var res11 = str3.concat(str4,str5,str6); alert(res11);//输出helloworldzhangsan var res12 = "abc".concat(); alert(res12);//输出abc
4.6 slice()方法
用于从原来字符串中取出子字符串并返回
1)slice()中有2个参数,第一个参数字符串的起始位置,第2个参数子字符串的结束位置
<span style="white-space:pre"> </span>var str7 = "hello world"; var res14 = str7.slice(6,11); alert(res14);
2)如果slice省略第二个参数,则表示字符串一直到整个字符串结束位置
<span style="white-space:pre"> </span>var res15 = str7.slice(6); alert(res15);//输出结果也为world
3) 如果该函数只有一个参数,且为负值,则从字符串结尾开始(从右向左)计算位置
<span style="white-space:pre"> </span>var res16 = str7.slice(-5);// alert(res16);//输出world var res17 = str7.slice(12,5);//返回空字符串 alert(res17);//输出为空
4.7 substring()方法
从原字符串中取出子字符串,跟slice使用一样,一般优先使用slice函数
<span style="white-space:pre"> </span>var str8 = "helloworld"; var str18 = str8.substring(0,5);//输出hello
如果该函数的第一个参数大于第二个参数,系统会自动调换2个数的位置
<span style="white-space:pre"> </span>var str18 = str8.substring(5,0); var res20 = str8.substring(0,-4);//会把-4变成0,返回为空字符串
4.8 substr()方法
从原字符串取出子字符串,并返回
1)两个参数(第一个参数:字符的起始位置;第2个参数:取出字符的个数)情况
<span style="white-space:pre"> </span>var res22 = "asdfghjkl".substr(2,5);//dfghj
2)省略第二个参数表示一直到字符串的结束
var res22 = "asdfghjkl".substr(4);//ghjkl
3)如果第一个参数是负数,从右向左计数
var res23 = "asdfghjkl".substr(-2);//kl
4)该函数两个参数都是负值,第二个参数值是负值,则会自动转换为0
4.9 indexOf()和lastIndexOf()方法
1)这两个方法用于确定一个字符串在另外一个字符串中的起始位置,都返回一个整数,表示匹配的开始位置,如果返回-1表示不匹配
2)区别在于indexOf()从字符串的头部开始匹配;lastIndexOf()从字符串的尾部开始匹配
<span style="white-space:pre"> </span>var stri = "adcdssed".indexOf("cds");//从左到右第一次出现的位置 var stri1 = "aslskkd".lastIndexOf("s");//从右到左第一次出现的位置 alert(stri);//输出2 alert(stri1);//输出3