3.JS
1.简介
JavaScript 因为互联网而生,紧随着浏览器的出现而问世
1997年7月,ECMAScript 1.0发布。
1998年6月,ECMAScript 2.0版发布。
1999年12月,ECMAScript 3.0版发布,成为JavaScript的通行标准,得到了广泛支持。
2007年10月,ECMAScript 4.0版草案发布,对3.0版做了大幅升级,预计次年8月发布正式版本。草案发布后,由于4.0版的目标过于激进,各方对于是否通过这个标准,发生了严重分歧。以Yahoo、Microsoft、Google为首的大公司,反对JavaScript的大幅升级,主张小幅改动;以JavaScript创造者Brendan Eich为首的Mozilla公司,则坚持当前的草案。
2008年7月,由于对于下一个版本应该包括哪些功能,各方分歧太大,争论过于激进,ECMA开会决定,中止ECMAScript 4.0的开发(即废除了这个版本),将其中涉及现有功能改善的一小部分,发布为ECMAScript 3.1,而将其他激进的设想扩大范围,放入以后的版本,由于会议的气氛,该版本的项目代号起名为Harmony(和谐)。会后不久,ECMAScript 3.1就改名为ECMAScript 5。
2009年12月,ECMAScript 5.0版正式发布。Harmony项目则一分为二,一些较为可行的设想定名为JavaScript.next继续开发,后来演变成ECMAScript 6;一些不是很成熟的设想,则被视为JavaScript.next.next,在更远的将来再考虑推出。TC39的总体考虑是,ECMAScript 5与ECMAScript 3基本保持兼容,较大的语法修正和新功能加入,将由JavaScript.next完成。当时,JavaScript.next指的是ECMAScript 6。第六版发布以后,将指ECMAScript 7。TC39预计,ECMAScript 5会在2013年的年中成为JavaScript开发的主流标准,并在此后五年中一直保持这个位置。
2011年6月,ECMAscript 5.1版发布,并且成为ISO国际标准(ISO/IEC 16262:2011)。到了2012年底,所有主要浏览器都支持ECMAScript 5.1版的全部功能。
2013年3月,ECMAScript 6草案冻结,不再添加新功能。新的功能设想将被放到ECMAScript 7。
2013年12月,ECMAScript 6草案发布。然后是12个月的讨论期,听取各方反馈。
2015年6月,ECMAScript 6正式发布,并且更名为“ECMAScript 2015”。这是因为TC39委员会计划,以后每年发布一个ECMAScirpt的版本,下一个版本在2016年发布,称为“ECMAScript 2016”。
除了ECMAScript的版本,很长一段时间中,Netscape公司(以及继承它的Mozilla基金会)在内部依然使用自己的版本号。这导致了JavaScript有自己不同于ECMAScript的版本号。1996年3月,Navigator 2.0内置了JavaScript 1.0。JavaScript 1.1版对应ECMAScript 1.0,但是直到JavaScript 1.4版才完全兼容ECMAScript 1.0。JavaScript 1.5版完全兼容ECMAScript 3.0。目前的JavaScript 1.8版完全兼容ECMAScript 5。
2.JS的引入方式
2.1 嵌入式
- <script>
- console.log('hello yuan')
- </script>
2.2 导入式
- <script src="hello.js"></script>
3.基本语法
3.1变量
- // 方式1 先声明再赋值
- var 变量名; // 声明的变量如果没有进行赋值,或者没有被定义的变量,值默认是undefined
- 变量名 = 变量值;
- // 方式2 声明并赋值
- var 变量名 = 变量值;
- // 方式3 一行可以声明多个变量.并且可以是不同类型
- var name="yuan", age=20, job="lecturer";
1、声明变量时 可以不用var. 如果不用var 那么它是全局变量
2、变量命名,首字符只能是字母,下划线,$美元符 三选一,余下的字符可以是下划线、美元符号或任何字母或数字字符且区分大小写
3.2注释
- // 单行注释
- /*
- 多行注释
- */
3.3语句分隔符
- var a = 1; // 分号和换行符作为语句分隔符号
- var b = 2;
- console.log(a,b);
4.基本数据类型
4.1 数字类型
JavaScript 没有整型和浮点型,只有一种数字类型,即number类型
- var x = 10;
- var y = 3.14;
- console.log(x,typeof x); // 10 "number"
- console.log(y,typeof y); // 3.14 "number"
4.2 字符串
字符串创建(两种方式)
变量 = “字符串”
字串对象名称 = new String (字符串)
- var str1="hello world";
- var str1= new String("hello word");
字符串常用方法
- var str = "hello";
- console.log(str);
- // length 计算字符串的长度
- console.log( str.length );
- // 字符串对象内置方法
- // toUpperCase(); 字母大写转换
- // toLowerCase(); 字母小写转换
- console.log( str.toUpperCase() );
- console.log( str.toLowerCase() );
- // indexOf 获取指定字符在字符串中第一次出现的索引位置
- // 字符串也有下标,也可以使用中括号来提取字符串的指定字符
- console.log(str[1]); // e
- console.log( str.indexOf("e") ); // 1
- // 切片,当前方法支持使用负数代表倒数下标
- // slice(开始下标) 从开始位置切到最后
- // slice(开始下标,结束下标) 从开始下标切到指定位置之前
- var str = "helloworld";
- var ret = str.slice(3,6); // 开区间,不包含结束下标的内容
- console.log(ret); // low
- var ret = str.slice(5);
- console.log(ret); // world
- var ret = str.slice(2,-1);
- console.log(ret); // lloworl
- var ret = str.slice(-4,-1);
- console.log(ret); // orl
- var ret = str.slice(-1,-4);
- console.log(ret); // orl
- // split 正则分割,经常用于把字符串转换成数组
- var str = "广东-深圳-南山";
- var ret = str.split("-");
- console.log( ret );
- // substr 截取
- var str = "hello world";
- var ret = str.substr(0,3);
- console.log(ret); // hel
- // trim 移除字符串首尾空白
- var password = " ge llo ";
- var ret = password.trim();
- console.log(password.length); // 13
- console.log(ret.length); // 6
4.3 布尔值
Boolean类型仅有两个值:true和false,也代表1和0,实际运算中true=1,false=0
- console.log(true);
- console.log(false);
4.4 空值
undefined类型
(1)当声明的变量未初始化时,该变量的默认值是 undefined。
(2)当函数无明确返回值时,返回的也是值 undefined;null类型
另一种只有一个值的类型是 null,它只有一个专用值 null,即它的字面量。值 undefined 实际上是从值 null 派生来的,因此 ECMAScript 把它们定义为相等的。
尽管这两个值相等,但它们的含义不同。undefined 是声明了变量但未对其初始化时赋予该变量的值,null 则用于表示尚未存在的对象。如果函数或方法要返回的是对象,那么找不到该对象时,返回的通常是 null。
4.5 类型转换
js中,类型转换有2种.一种就是强制转换,一种就是自动转换.
强制转换
- // 1. 转换数据为数值类型
- // parseInt 把数据转换成整数
- // parseFloat 把数据转换成小数
- // Number 把数据转换成数值
- var box1 = "一共100件"; // 转换会失败
- var box1 = "100件"; // 转换会成功
- var ret = parseInt(box1);
- console.log(box1);
- console.log(ret);
-
- var box2 = "3.14";
- console.log(parseFloat(box2) ); // 3.14
-
- var box3 = "3.14"; // 使用Number转换的数据里面必须是纯数字!!!!否则都会转换失败
- // var box3 = "3.1.4"; // 转换失败!
- console.log( Number(box3) );
-
- // 对于转换数值,如果转换失败的话,则结果为 NaN ,是 Not a Number ,但是NaN的类型也是number类型
-
- // 2. 转换数据为字符串
- // 变量.toString()
- // String(数据)
- var box4 = 3.14;
- var ret = box4.toString();
- console.log(ret);
-
- ret = String(box4);
- console.log(ret);
-
- // 3. 转换数据成布尔类型
- // Boolean()
-
- var box5 = "";
- console.log( Boolean(box5) ); // false
- var box6 = -1;
- console.log( Boolean(box6) ); // true
- var box7 = 0;
- console.log( Boolean(box7) ); // false;
- var box8 = "false";
- console.log( Boolean(box8) ); // true
- var box9 = [];
- console.log( Boolean(box9) ); // true
- var box10 = {};
- console.log( Boolean(box10) ); // true
- var box11 = "0";
- console.log( Boolean(box11) ); // true
- var box12 = null;
- console.log( Boolean(box12) ); // false
- var box13 = undefined;
- console.log( Boolean(box13) ); // false
- // 1. 转换数据为数值类型
自动转换
- // 所谓的自动转换,其实弱类型中的变量会根据当前代码的需要,进行类型的自动隐式转化
- var box1 = 1 + true;
- // true 转换成数值,是1, false转换成数值,是0
- console.log(box1); // 2
-
- var box2 = 1 + "200";
- console.log(box2); // 1200 原因是,程序中+的含义有2种,第一: 两边数值相加, 第二: 两边字符串拼接.但是在js中运算符的优先级中, 字符串拼接的优先级要高于数值的加减乘除,所以解析器优先使用了+号作为了字符串的拼接符号了,因为程序就需要+号两边都是字符串才能完成运算操作,因此1变成字符串最终的结果就是 "1" +"200"
-
- var box3 = 1 - "200";
- console.log(box3); // -199;因为-号中表示的就是左边的数值减去右边的数值,因此程序就会要求"200"是数值,因此内部偷偷的转换了一下
- // 所谓的自动转换,其实弱类型中的变量会根据当前代码的需要,进行类型的自动隐式转化
5.运算符
- /*
- //算术运算符
- + 数值相加
- - 数值相减
- * 数值相乘
- / 数值相除
- % 数值求余
- ** 数值求幂
- a++ 数值后自增1 a=a+1
- ++a 数值前自增1 a=a+1
- b-- 数值后自减1 b=b-1
- --b 数值前自减1 b=b-1
- //赋值运算符
- =
- +=
- -=
- *=
- /=
- %=
- **=
- //比较运算符,比较的结果要么是true, 要么是false
- > 大于
- < 小于
- >= 大于或者等于
- <= 小于或者等于
- != 不等于[计算数值]
- == 等于[计算]
- !== 不全等[不仅判断数值,还会判断类型是否一致]
- === 全等[不仅判断数值,还会判断类型是否一致]
- //逻辑运算符
- && 并且 and 两边的运算结果为true,最终结果才是true
- || 或者 or 两边的运算结果为false,最终结果才是false
- ! 非 not 运算符的结果如果是true,则最终结果是false ,反之亦然.
- //逻辑运算符进阶用法:
- 1. 实现短路
- var a = false || 2 >>> a = 2
- var a = true && "hehe" >>> a = "hehe"
- 2. 快速布尔化[把数据快速转换成布尔类型]
- var a = 100
- !!a >>> true
- //条件运算符[三目运算符]
- 条件?true:false
- 例如:
- var age = 12;
- var ret = age>=18?"成年":"未成年"; // 相当于 python中的"成年" if age >= 18 else "未成年"
- console.log(ret);
- */
6.流程控制语句
编程语言的流程控制分为三种:
顺序结构(从上向下顺序执行)
分支结构
循环结构
之前我们学习的方式就是顺序执行,即代码的执行从上到下,一行行分别执行。
6.1 分支结构
if 分支语句
- if(条件){
- // 条件为true时,执行的代码
- }
- if(条件){
- // 条件为true时,执行的代码
- }else{
- // 条件为false时,执行的代码
- }
- if(条件1){
- // 条件1为true时,执行的代码
- }else if(条件2){
- // 条件2为true时,执行的代码
- }....
- }else{
- // 上述条件都不成立的时候,执行的代码
- }
- if(条件){
switch语句
- switch(条件){
- case 结果1:
- 满足条件执行的结果是结果1时,执行这里的代码..
- break;
- case 结果2:
- 满足条件执行的结果是结果2时,执行这里的代码..
- break;
- .....
- default:
- 条件和上述所有结果都不相等时,则执行这里的代码
- }
- switch(条件){
1、switch比if else更为简洁
2、执行效率更高。switch…case会生成一个跳转表来指示实际的case分支的地址,而这个跳转表的索引号与switch变量的值是相等的。从而,switch…case不用像if…else那样遍历条件分支直到命中条件,而只需访问对应索引号的表项从而到达定位分支的目的。
3、到底使用哪一个选择语句,代码环境有关,如果是范围取值,则使用if else语句更为快捷;如果是确定取值,则使用switch是更优方案。
6.2 循环结构
while循环
- while(循环的条件){
- // 循环条件为true的时候,会执行这里的代码
- }
- while(循环的条件){
for循环
- // 循环三要素
- for(1.声明循环的开始; 2.条件; 4. 循环的计数){
- // 3. 循环条件为true的时候,会执行这里的代码
- }
-
- for(循环的成员下标 in 被循环的数据){
- // 当被循环的数据一直没有执行到最后下标,都会不断执行这里的代码
- }
- // 循环三要素
退出循环(break和continue)
- for (var i = 0;i<100;i++){
- if (i===88){
- continue // 退出当次循环
- // break // 退出当前整个循环
- }
- console.log(i)
- }
- for (var i = 0;i<100;i++){
7.数组对象
创建数组
- 创建方式1:
- var arrname = [元素0,元素1,….]; // var arr=[1,2,3];
-
- 创建方式2:
- var arrname = new Array(元素0,元素1,….); // var test=new Array(100,"a",true);
- 创建方式1:
遍历
- var arr = [111,222,333]
- for (var i in arr){
- console.log(i,arr[i])
- }
- var arr = [111,222,333]
数组方法
- var arr = ["A","B","C","D"];
- // (1) pop() 出栈,删除最后一个成员作为返回值
- var arr = [1,2,3,4,5];
- var ret = arr.pop();
- console.log(arr); // [1, 2, 3, 4]
- console.log(ret); // 5
- // (2) push() 入栈,给数组后面追加成员
- var arr = [1,2,3,4,5];
- arr.push("a");
- console.log(arr); // [1, 2, 3, 4, 5, "a"]
- // (3) shift是将数组的第一个元素删除
- var arr = [1,2,3,4,5];
- arr.shift()
- console.log(arr); // [2, 3, 4, 5]
- // (4) unshift是将value值插入到数组的开始
- var arr = [1,2,3,4,5];
- arr.unshift("yuan")
- console.log(arr); // ["yuan",1,2, 3, 4, 5]
- // (5) reverse() 反转排列
- var arr = [1,2,3,4,5];
- arr.reverse();
- console.log(arr); // [5, 4, 3, 2, 1]
- // (6) slice(开始下标,结束下标) 切片,开区间
- // (7) sort() 排序
- var arr = [3,4,1,2,5,10];
- console.log( arr ); // [3, 4, 1, 2, 5, 10]
- arr.sort();
- //
- // // 这是字符的排序,不是数值的排序
- console.log(arr); // [1, 10, 2, 3, 4, 5]
- // 数值升序
- var arr = [3,4,1,2,5,10];
- arr.sort(function(a,b){
- return a-b;
- });
- console.log(arr); // [1, 2, 3, 4, 5, 10]
- // 数值降序
- var arr = [3,4,1,2,5,10];
- arr.sort(function(a,b){
- return b-a;
- });
- console.log(arr); // [10, 5, 4, 3, 2, 1]
- // (8) splice(操作位置的下标,删除操作的成员长度,"替换或者添加的成员1","替换或者添加的成员2") 添加/删除指定的成员 "万能函数"
- var arr1 = [1,2,3];
- arr1.splice(1,1);
- console.log(arr1); // 删除指定的1个成员 [1, 3]
- var arr2 = ["a","b","c","d"];
- arr2.splice(2,0,"w","x","w"); // 添加
- console.log(arr2); // ["a", "b", "w", "x", "w", "c", "d"]
- var arr3 = ["a","b","c"];
- arr3.splice(1,1,"w");
- console.log(arr3); // ["a", "w", "c"]
- // (9) concat() 把2个或者多个数组合并
- var arr1 = [1,2,3];
- var arr2 = [4,5,7];
- var ret = arr1.concat(arr2);
- console.log( ret );
- // (10) join() 把数组的每一个成员按照指定的符号进行拼接成字符串
- var str = "广东-深圳-南山";
- var arr = str.split("-");
- console.log( arr ); // ["广东", "深圳", "南山"];
- var arr1 = ["广东", "深圳", "南山"];
- var str1 = arr1.join("-");
- console.log( str1 ); // 广东-深圳-南山
- // (11) find() 高阶函数, 返回符合条件的第一个成员
- var arr = [4,6,5,7];
- var func = (num)=>{
- if(num%2===0){
- return num;
- }
- };
- var ret = arr.find(func);
- console.log( ret ); // 4
- // (12) filter() 高阶函数, 对数组的每一个成员进行过滤,返回符合条件的结果
- var arr = [4,6,5,7];
- function func(num){ // 也可以使用匿名函数或者箭头函数
- if(num%2===0){
- return num;
- }
- }
- var ret = arr.filter(func); // 所有的函数名都可以作为参数传递到另一个函数中被执行
- console.log( ret );
- // (13) map() 对数组的每一个成员进行处理,返回处理后的每一个成员
- var arr = [1,2,3,4,5];
- var ret = arr.map((num)=>{
- return num**3;
- });
- console.log( ret ); // [1, 8, 27, 64, 125]
- // (14) 其它方法
- // includes 查询指定数据是否在数组中存在!
- // indexOf() 查询指定数据在数组中第一次出现的位置
- // isArray() 判断变量的值是否是数组
8.Object对象
Object 的实例不具备多少功能,但对于在应用程序中存储和传输数据而言,它们确实是非常理想的选择。
创建对象
- // 方式一
- var person = new Object();
- person.name = "alvin";
- person.age = 18;
-
- // 方式二
- var person = {
- name : "alvin",
- age : 18
- };
- // 方式一
访问成员 object可以通过. 和 []来访问。
- console.log(person["age"]);
- console.log(person.age)
- console.log(person["age"]);
遍历
- for (var attr in person){
- console.log(attr,person[attr]);
- }
- for (var attr in person){
序列化和反序列化
- var data = {
- name: "xiaoming",
- age: 22,
- };
-
- // 把json对象转换成json字符串
- var ret = JSON.stringify(data);
- console.log(ret ); // {"name":"xiaoming","age":22}
-
- // 把json字符串转换成json对象
- var str = `{"name":"xiaoming","age":22}`;
- var ret = JSON.parse(str);
- console.log(ret);
- var data = {
9.Data对象
创建Date对象
- //方法1:不指定参数
- var nowd1=new Date();
- console.log(nowd1.toLocaleString( ));
-
- //方法2:参数为日期字符串
- var d2=new Date("2004/3/20 11:12");
- console.log(d2.toLocaleString( ));
- var d3=new Date("04/03/20 11:12");
- console.log(d3.toLocaleString( ));
-
- //方法3:参数为毫秒数
- var d4=new Date(5000);
- console.log(d4.toLocaleString( ));
- console.log(d4.toUTCString());
-
- //方法4:参数为年月日小时分钟秒毫秒
- var d5=new Date(2004,2,20,11,12,0,300);
- console.log(d5.toLocaleString( ));//毫秒并不直接显示
- //方法1:不指定参数
获取时间信息
- 获取日期和时间
- getDate() 获取日
- getDay () 获取星期
- getMonth () 获取月(0-11)
- getFullYear () 获取完整年份
- getYear () 获取年
- getHours () 获取小时
- getMinutes () 获取分钟
- getSeconds () 获取秒
- getMilliseconds () 获取毫秒
- getTime () 返回累计毫秒数(从1970/1/1午夜)
- 获取日期和时间
日期和时间的转换
- 日期和时间的转换:
- // 返回国际标准时间字符串
- toUTCString()
- // 返回本地格式时间字符串
- toLocalString()
- // 返回累计毫秒数(从1970/1/1午夜到本地时间)
- Date.parse(x)
- // 返回累计毫秒数(从1970/1/1午夜到国际时间)
- Date.UTC(x)
- function getCurrentDate(){
- //1. 创建Date对象
- var date = new Date(); //没有填入任何参数那么就是当前时间
- //2. 获得当前年份
- var year = date.getFullYear();
- //3. 获得当前月份 js中月份是从0到11.
- var month = date.getMonth()+1;
- //4. 获得当前日
- var day = date.getDate();
- //5. 获得当前小时
- var hour = date.getHours();
- //6. 获得当前分钟
- var min = date.getMinutes();
- //7. 获得当前秒
- var sec = date.getSeconds();
- //8. 获得当前星期
- var week = date.getDay(); //没有getWeek
- // 2014年06月18日 15:40:30 星期三
- return year+"年"+changeNum(month)+"月"+day+"日 "+hour+":"+min+":"+sec+" "+parseWeek(week);
- }
- 日期和时间的转换:
10.Math对象
- // Number对象的内置方法
- // toFixed(x) 保留小数位
- var num = 100.3;
- var ret = num.toFixed(2);
- console.log(num); // 100.3
- console.log(ret); // 100.30
- // Math对象的内置方法
- // abs(x) 返回数值的绝对值
- // var num = -10;
- console.log( Math.abs(num) ); // 10
- // ceil(x) 向上取整
- var num = 10.3;
- console.log( Math.ceil(num) ); // 11
- // floor(x) 向下取整
- var num = 10.3;
- console.log( Math.floor(num) ); // 10
- // max(x,y,z,...,n)
- console.log( Math.max(3,56,3) ); // 56
- // min(x,y,z,...,n)
- // pow(x,y)
- console.log(Math.pow(3, 2)); // 相等于 3**2
- console.log( 3**2 ); // 使用这个,上面废弃
- // random() 生成0-1随机数
- console.log( Math.random() );
- // 生成0-10之间的数值
- console.log( Math.random() * 10 );
- // round(x) 四舍五入
- // 生成0-10之间的整数
- console.log( Math.round( Math.random() * 10 ) );
11.Function对象
函数在程序中代表的就是一段具有功能性的代码,可以让我们的程序编程更加具有结构性和提升程序的复用性,也能让代码变得更加灵活强大
11.1 声明函数
- // 函数的定义方式1
- function 函数名 (参数){
- 函数体;
- return 返回值;
- }
- 功能说明:
- 可以使用变量、常量或表达式作为函数调用的参数
- 函数由关键字function定义
- 函数名的定义规则与标识符一致,大小写是敏感的
- 返回值必须使用return
- // 函数的定义方式2
- 用 Function 类直接创建函数的语法如下:
- var 函数名 = new Function("参数1","参数n","function_body");
- 虽然由于字符串的关系,第二种形式写起来有些困难,但有助于理解函数只不过是一种引用类型,它们的行为与用 Function 类明确创建的函数行为是相同的。
11.2 函数调用
- //f(); --->OK
- function f(){
- console.log("hello")
- }
- f() //----->OK
不同于python,js代码在运行时,会分为两大部分———预编译 和 执行阶段。
预编译:会先检测代码的语法错误,进行变量、函数的声明。
执行阶段:变量的赋值、函数的调用等,都属于执行阶段。
11.3 函数参数
- // 位置参数
- function add(a,b){
- console.log(a);
- console.log(b);
- }
- add(1,2)
- add(1,2,3)
- add(1)
- // 默认参数
- function stu_info(name,gender="male"){
- console.log("姓名:"+name+" 性别:"+gender)
- }
- stu_info("yuan")
11.4 函数返回值
在函数体内,使用 return 语句可以设置函数的返回值。一旦执行 return 语句,将停止函数的运行,并运算和返回 return 后面的表达式的值。如果函数不包含 return 语句,则执行完函数体内每条语句后,返回 undefined 值。
- function add(x,y) {
- return x+y
- }
- var ret = add(2,5);
- console.log(ret)
11.5 匿名函数
匿名函数,即没有变量名的函数。在实际开发中使用的频率非常高!也是学好JS的重点。
- // 匿名函数赋值变量
- var foo = function () {
- console.log("这是一个匿名函数!")
- };
- // 匿名函数的自执行
- (function (x,y) {
- console.log(x+y);
- })(2,3)
- // 匿名函数作为一个高阶函数使用
- function bar() {
- return function () {
- console.log("inner函数!")
- }
- }
- bar()()
11.6 函数作用域
变量的作用域有全局作用域和局部作用域两种。
- // 局部变量,是在函数内部声明,它的生命周期在当前函数被调用的时候, 当函数调用完毕以后,则内存中自动销毁当前变量
- // 全局变量,是在函数外部声明,它的生命周期在当前文件中被声明以后就保存在内存中,直到当前文件执行完毕以后,才会被内存销毁掉
11.7 JS预编译
js运行三个阶段:
语法分析
预编译
解释执行
预编译可分为全局预编译和局部预编译。
在js脚本加载之后,会先通篇检查是否存在低级错误;
在语法检测完之后,便进行全局预编译;
在全局预编译之后,就解释一行,执行一行;
当执行到函数调用那一行前一刻,会先进行函数预编译,再往下执行。
全局预编译的3个步骤:
创建GO对象(Global Object)全局对象,即window对象。
找变量声明,将变量名作为GO属性名,值为undefined
查找函数声明,作为GO属性,值赋予函数体
局部预编译的4个步骤:
创建AO对象(Activation Object)执行期上下文。
找形参和变量声明,将变量和形参名作为AO属性名,值为undefined
将实参值和形参统一。
在函数体里面找函数声明,值赋予函数体。
GO对象是全局预编译,所以它优先于AO对象所创建和执行
局预编译
- GO/window = {
- a: undefined,
- c: undefined,
- foo: function(a) {
- console.log(a);
- var a = 123;
- console.log(a);
- function a() {}
- console.log(a);
- var b = function() {}
- console.log(b);
- function d() {}
- }
- }
解释执行代码(直到执行调用函数foo(20)语句)
- GO/window = {
- a: 10,
- c: function (){
- console.log("I at C function");
- }
- test: function(a) {
- console.log(a);
- var a = 123;
- console.log(a);
- function a() {}
- console.log(a);
- var b = function() {}
- console.log(b);
- function d() {}
- }
- }
调用函数foo(20)前发生布局预编译
- // 局部预编译前两步:
- AO = {
- a:undefined,
- b:undefined,
- }
-
- // 局部预编译第三步:
- AO = {
- a:20,
- b:undefined,
- }
- // 局部预编译第四步:
- AO = {
- a:function a() {},
- b:undefined
- d:function d() {}
- }
预编译总结:
函数声明整体提升-(具体点说,无论函数调用和声明的位置是前是后,系统总会把函数声明移到调用前面)
变量 声明提升-(具体点说,无论变量调用和声明的位置是前是后,系统总会把声明移到调用前,注意仅仅只是声明,所以值是undefined)
面试题:
- var num3 = 10;
- function func3(){
- console.log(num3);
- var num3 = 20;
- }
- func3();
- console.log(num3);
-
-
- /*
-
- // 全局编译
-
- GO{
- num3:undefined,
- func3: function (){
- console.log(num3);
- var num3 = 20;
- }
-
- // 全局执行
- var num3 = 10;
- GO{
- num3:10,
- func3: function (){
- console.log(num3);
- var num3 = 20;
- }
-
-
- // 局部编译
- func3.AO{
- num3:undefined,
- }
-
-
- // 局部执行
-
- func3.AO{
- num3:20,
- }
-
- // 全局执行
-
- GO.num3 = 10
- }
-
- */
12.BOM对象
BOM:Broswer object model,即浏览器提供我们开发者在javascript用于操作浏览器的对象。
12.1 window对象
窗口方法
- // BOM Browser object model 浏览器对象模型
-
- // js中最大的一个对象.整个浏览器窗口出现的所有东西都是window对象的内容.
- console.log( window );
-
- // alert() 弹出一个警告框
- window.alert("hello");
-
- //confirm 弹出一个确认框,点击确认,返回true, 点击取消,返回false
- var ret = confirm("您确认要删除当前文件么?");
- console.log( ret );
-
- // 弹出一个消息输入框,当点击确认以后,则返回可以接收到用户在输入框填写的内容.如果点击取消,则返回null
- var ret = prompt("请输入一个内容","默认值");
- console.log( ret );
-
- // close() 关闭当前浏览器窗口
- window.close();
-
- //打开一个新的浏览器窗口
- window.open("http://www.baidu.com","_blank","width=800px,height=500px,left=200px,top=200px";
- // BOM Browser object model 浏览器对象模型
定时方法 setInterval() 方法会不停地调用函数,直到 clearInterval() 被调用或窗口被关闭。由 setInterval() 返回的 ID 值可用作 clearInterval() 方法的参数。而setTimeout是在指定的毫秒数后调用code一次。
-
- // 设置循环定时器
- var ID = window.setInterval(code,millisec) // 每millisec毫秒执行一次code
- // 取消循环定时器
- window.clearInterval(ID);
-
- // 设置单次定时器
- var ID = window.setTimeout(code,millisec) // millisec毫秒后执行code一次
- // 取消单次定时器
- window.clearTimeout(ID);
-
12.2 Location对象
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- </head>
- <body>
- <button onclick="func1()">查看Location对象</button>
- <button onclick="func2()">跳转到百度</button>
- <button onclick="func3()">F5</button>
- <script>
- function func1(){
- console.log( location );
- }
- // 地址栏对象控制和操作地址栏
- // 所谓的地址就是当前页面所在地址
- // 地址结构:
- // 协议://域名:端口/路径/文件名?查询字符串#锚点
- console.log( `协议=>${location.protocol}` );
- console.log( `端口=>${location.port}` );
- console.log( `域名=>${location.hostname}` );
- console.log( `域名:端口=>${location.host}` );
- console.log( `路径=>${location.pathname}` );
- console.log( `查询字符串=>${location.search}` );
- console.log(`完整的地址信息=>${location.href}`);
-
- function func2(){
- // location.href="http://www.baidu.com"; // 页面跳转
- location.assign("http://www.baidu.com"); // 页面跳转
- }
-
- function func3(){
- location.reload(); // 刷新页面
- }
- </script>
- </body>
- </html>
12.3 本地存储对象
使用存储对象的过程中, 对象数据会根据域名端口进行保存的,所以 js不能获取当前页面以外其他域名端口保存到本地的数据。也就是说,我们存储对象获取数据只能是自己当前端口或者域名下曾经设置过的数据,一旦端口或者域名改变,则无法获取原来的数据。
- localStorage 本地永久存储
- localStorage.setItem("变量名","变量值"); 保存一个数据到存储对象
- localStorage.变量名 = 变量值 保存一个数据到存储对象
-
- localStorage.getItem("变量名") 获取存储对象中保存的指定变量对应的数据
- localStorage.变量名 获取存储对象中保存的指定变量对应的数据
-
- localStorage.removeItem("变量名") 从存储对象中删除一个指定变量对应的数据
- localStorage.clear() 从存储对象中删除所有数据
-
- sessionStorage 本地会话存储
- sessionStorage.setItem("变量名","变量值"); 保存一个数据到存储对象
- sessionStorage.变量名 = 变量值 保存一个数据到存储对象
-
- sessionStorage.getItem("变量名") 获取存储对象中保存的指定变量对应的数据
- sessionStorage.变量名 获取存储对象中保存的指定变量对应的数据
-
- sessionStorage.removeItem("变量名") 从存储对象中删除一个指定变量对应的数据
- sessionStorage.clear() 从存储对象中删除所有数据
- localStorage和sessionStorage的区别:
-
- 1、localStorage和sessionStorage一样都是用来存储客户端临时信息的对象。
-
- 2、他们均只能存储字符串类型的对象(虽然规范中可以存储其他原生类型的对象,但是目前为止没有浏览器对其进行实现)。
-
- 3、localStorage生命周期是永久,这意味着除非用户显示在浏览器提供的UI上清除localStorage信息,否则这些信息将永远存在。sessionStorage生命周期为当前窗口或标签页,一旦窗口或标签页被永久关闭了,那么所有通过sessionStorage存储的数据也就被清空了。
-
- 4、不同浏览器无法共享localStorage或sessionStorage中的信息。相同浏览器的不同页面间可以共享相同的 localStorage(页面属于相同域名和端口),但是不同页面或标签页间无法共享sessionStorage的信息。这里需要注意的是,页面及标 签页仅指顶级窗口,如果一个标签页包含多个iframe标签且他们属于同源页面,那么他们之间是可以共享sessionStorage的。
13.DOM对象
DOM document Object Model 文档对象模型
13.1 查找标签
直接查找标签
- document.getElementsByTagName("标签名")
- document.getElementById("id值")
- document.getElementsByClassName("类名")
- document.getElementsByTagName("标签名")
导航查找标签
- elementNode.parentElement // 父节点标签元素
- elementNode.children // 所有子标签
- elementNode.firstElementChild // 第一个子标签元素
- elementNode.lastElementChild // 最后一个子标签元素
- elementNode.nextElementSibling // 下一个兄弟标签元素
- elementNode.previousElementSibling // 上一个兄弟标签元素
- elementNode.parentElement // 父节点标签元素
CSS选择器查找
- document.querySelector("css选择器") //根据css选择符来获取查找到的第一个元素,返回标签对象(dom对象)
- document.querySelectorAll("css选择器"); // 根据css选择符来获取查找到的所有元素,返回数组
- document.querySelector("css选择器") //根据css选择符来获取查找到的第一个元素,返回标签对象(dom对象)


- 1 <!DOCTYPE html>
- 2 <html lang="en">
- 3 <head>
- 4 <meta charset="UTF-8">
- 5 <title>Title</title>
- 6 </head>
- 7 <body>
- 8
- 9
- 10 <div id="i1">DIV1</div>
- 11
- 12 <div class="c1">DIV</div>
- 13 <div class="c1">DIV</div>
- 14 <div class="c1">DIV</div>
- 15
- 16
- 17 <div class="outer">
- 18 <div class="c1">item</div>
- 19 </div>
- 20
- 21
- 22 <div class="c2">
- 23 <div class="c3">
- 24 <ul class="c4">
- 25 <li class="c5" id="i2">111</li>
- 26 <li>222</li>
- 27 <li>333</li>
- 28 </ul>
- 29 </div>
- 30 </div>
- 31
- 32 <script>
- 33
- 34 // 直接查找
- 35
- 36 var ele = document.getElementById("i1"); // ele就是一个dom对象
- 37 console.log(ele);
- 38
- 39 var eles = document.getElementsByClassName("c1"); // eles是一个数组 [dom1,dom2,...]
- 40 console.log(eles);
- 41
- 42 var eles2 = document.getElementsByTagName("div"); // eles2是一个数组 [dom1,dom2,...]
- 43 console.log(eles2);
- 44
- 45 var outer = document.getElementsByClassName("outer")[0];
- 46 var te = outer.getElementsByClassName("c1");
- 47 console.log(te);
- 48
- 49 // 导航查找
- 50
- 51 var c5 = document.getElementsByClassName("c5")[0];
- 52 console.log(c5); // c5是一个DOM对象
- 53
- 54 console.log(c5.parentElement.lastElementChild); // 返回值是dom对象
- 55 console.log(c5.parentElement.children); // 返回值是dom对象数组
- 56 console.log(c5.nextElementSibling.nextElementSibling);
- 57 console.log(c5.parentElement.children);
- 58
- 59 // css选择器
- 60
- 61 var dom = document.querySelector(".c2 .c3 .c5");
- 62 console.log(":::",dom);
- 63
- 64 var doms = document.querySelectorAll("ul li");
- 65 console.log(":::",doms);
- 66
- 67 </script>
- 68
- 69 </body>
- 70 </html>
- 71
- 72
13.2 绑定事件
静态绑定 :直接把事件写在标签元素中。
- <div id="div" onclick="foo(this)">click</div>
-
- <script>
- function foo(self){ // 形参不能是this;
- console.log("foo函数");
- console.log(self);
- }
- </script>
- <div id="div" onclick="foo(this)">click</div>
动态绑定:在js中通过代码获取元素对象,然后给这个对象进行后续绑定。
- <p id="i1">试一试!</p>
-
- <script>
-
- var ele=document.getElementById("i1");
-
- ele.onclick=function(){
- console.log("ok");
- console.log(this); // this直接用
- };
-
- </script>
- <p id="i1">试一试!</p>
13.3 操作标签
- <标签名 属性1=“属性值1” 属性2=“属性值2”……>文本</标签名>
文本操作
- <div class="c1"><span>click</span></div>
-
- <script>
-
- var ele =document.querySelector(".c1");
-
- ele.onclick = function (){
- // 查看标签文本
- console.log(this.innerHTML)
- console.log(this.innerText)
- }
-
- ele.ondblclick = function (){
- // 设置标签文本
- this.innerHTML = "<a href='#'>yuan</a>"
- //this.innerText = "<a href='#'>yuan</a>"
- }
-
- </script>
- <div class="c1"><span>click</span></div>
value操作
- <input type="text" id="i1" value="yuan">
- <textarea name="" id="i2" cols="30" rows="10">123</textarea>
- <select id="i3">
- <option value="hebei">河北省</option>
- <option value="hubei">湖北省</option>
- <option value="guangdong">广东省</option>
- </select>
-
- <script>
-
- // input标签
- var ele1 =document.getElementById("i1");
- console.log(ele1.value);
- ele1.onmouseover = function (){
- this.value = "alvin"
- }
-
- // textarea标签
- var ele2 =document.getElementById("i2");
- console.log(ele2.value);
- ele2.onmouseover = function (){
- this.innerText = "welcome to JS world!"
- this.value = "welcome to JS world!"
- }
- // select标签
- var ele3 =document.getElementById("i3");
- console.log(ele3.value);
- ele3.value= "hubei"
-
- </script>
- <input type="text" id="i1" value="yuan">
css样式操作
- <p id="i1">Hello world!</p>
-
- <script>
- var ele = document.getElementById("i1");
- ele.onclick = function (){
- this.style.color = "red"
- }
- </script>
- <p id="i1">Hello world!</p>
- 属性操作
- elementNode.setAttribute("属性名","属性值")
- elementNode.getAttribute("属性名")
- elementNode.removeAttribute("属性名");
- elementNode.setAttribute("属性名","属性值")
- class属性操作
- elementNode.className
- elementNode.classList.add
- elementNode.classList.remove
- elementNode.className
节点操作
- // 创建节点:
- document.createElement("标签名")
- // 插入节点
- somenode.appendChild(newnode) // 追加一个子节点(作为最后的子节点)
- somenode.insertBefore(newnode,某个节点) // 把增加的节点放到某个节点的前边
- // 删除节点
- somenode.removeChild():获得要删除的元素,通过父元素调用删除
- //替换节点
- somenode.replaceChild(newnode, 某个节点);
- // 创建节点:
13.4 常用事件
onload事件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
-
-
- <script>
- window.onload = function (){
- ele = document.getElementById("i1")
- console.log(ele.innerHTML);
- }
- </script>
- </head>
- <body>
-
- <div id="i1">yuan</div>
-
- </body>
- </html>
- <!DOCTYPE html>
onsubmit事件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
-
- </head>
- <body>
-
- <form action="" id="i1">
- 用户名:<input type="text">
- 密码: <input type="password">
- <input type="submit">
- </form>
-
-
- <script>
-
- var ele = document.getElementById("i1");
- var user = document.querySelector("#i1 [type=text]")
- var pwd = document.querySelector("#i1 [type=password]")
- ele.onsubmit = function (e){
- console.log(user.value);
- console.log(pwd.value);
-
- return false; // 终止事件执行
- // e.preventDefault() // 阻止元素默认行为
- }
-
- </script>
- </body>
- </html>
- <!DOCTYPE html>
onchange事件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
-
- </head>
- <body>
-
- <select name="provonce" id="s1">
- <option value="hebei">请选择省份</option>
- <option value="hubei">湖北省</option>
- <option value="hunan">湖南省</option>
- <option value="hebei">河北省</option>
- </select>
-
- <select name="provonce" id="s2">
- <option value="hebei">请选择城市</option>
-
- </select>
-
- <script>
-
- var data={"hunan":["长沙","岳阳","张家界"],"hubei":["武汉","襄阳","荆州"],"hebei":["石家庄","保定","张家口"]};
- console.log(data);
- var ele = document.getElementById("s1");
- var ele2 = document.getElementById("s2");
- ele.onchange=function () {
- console.log(this.value);
- var citys = data[this.value];
- console.log(citys);
- // 清空操作
- ele2.options.length=1;
- // 创建标签
- for (var i=0;i<citys.length;i++){
- var option = document.createElement("option"); // </option></option>
- option.innerHTML=citys[i];
- ele2.appendChild(option)
- }
- }
-
- </script>
-
-
- </body>
- </html>
- <!DOCTYPE html>
onmouse事件
- <!DOCTYPE html>
- <html lang="en">
- <head>
- <meta charset="UTF-8">
- <title>Title</title>
- <style>
- #container{
- width: 300px;
- }
- #title{
- cursor: pointer;
- background: #ccc;
- }
- #list{
- display: none;
- background:#fff;
- }
-
- #list div{
- line-height: 50px;
- }
- #list .item1{
- background-color: green;
- }
-
- #list .item2{
- background-color: rebeccapurple;
- }
-
- #list .item3{
- background-color: lemonchiffon;
- }
-
-
- </style>
- </head>
- <body>
- <div id="container">
- <div id="title">使用了mouseout事件↓</div>
- <div id="list">
- <div class="item1">第一行</div>
- <div class="item2">第二行</div>
- <div class="item3">第三行</div>
- </div>
- </div>
- <script>
-
- // 1.不论鼠标指针离开被选元素还是任何子元素,都会触发 mouseout 事件。
-
- // 2.只有在鼠标指针离开被选元素时,才会触发 mouseleave 事件。
-
- var container=document.getElementById("container");
- var title=document.getElementById("title");
- var list=document.getElementById("list");
- title.onmouseover=function(){
- list.style.display="block";
- };
-
- container.onmouseleave=function(){ // 改为onmouseout试一下
- list.style.display="none";
- };
-
- /*
-
- 因为mouseout事件是会冒泡的,也就是onmouseout事件可能被同时绑定到了container的子元素title和list
- 上,所以鼠标移出每个子元素时也都会触发我们的list.style.display="none";
-
- */
- </script>
- </body>
- </html>
- <!DOCTYPE html>
onkey事件
- <input type="text" id="t1"/>
-
- <script type="text/javascript">
-
- var ele=document.getElementById("t1");
-
- ele.onkeydown=function(e){
- console.log("onkeydown",e.key)
- };
-
- ele.onkeyup=function(e){
- console.log("onkeyup",e.key)
- };
- </script>
- onblur和onfocus事件
- <input type="text" class="c1">
-
-
- <script>
-
- var ele = document.querySelector(".c1");
-
- // 获取焦点事件
- ele.onfocus = function () {
- console.log("in")
- };
-
- // 失去焦点事件
- ele.onblur = function () {
- console.log("out")
- }
-
- </script>
- <input type="text" id="t1"/>
冒泡事件
- <div class="c1">
- <div class="c2"></div>
- </div>
-
-
- <script>
-
- var ele1 = document.querySelector(".c1");
- ele1.onclick = function () {
- alert("c1区域")
- };
-
- var ele2 = document.querySelector(".c2");
- ele2.onclick = function (event) {
- alert("c2区域");
- // 如何阻止事件冒泡
- event.stopPropagation();
- }
-
- </script>
- <div class="c1">
3.JS的更多相关文章
- Vue.js 和 MVVM 小细节
MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,其核心是提供对View 和 ViewModel 的双向数据绑定,这使得ViewModel 的状态改变可以自 ...
- js学习笔记:操作iframe
iframe可以说是比较老得话题了,而且网上也基本上在说少用iframe,其原因大致为:堵塞页面加载.安全问题.兼容性问题.搜索引擎抓取不到等等,不过相对于这些缺点,iframe的优点更牛,跨域请求. ...
- js学习笔记:webpack基础入门(一)
之前听说过webpack,今天想正式的接触一下,先跟着webpack的官方用户指南走: 在这里有: 如何安装webpack 如何使用webpack 如何使用loader 如何使用webpack的开发者 ...
- JS调用Android、Ios原生控件
在上一篇博客中已经和大家聊了,关于JS与Android.Ios原生控件之间相互通信的详细代码实现,今天我们一起聊一下JS调用Android.Ios通信的相同点和不同点,以便帮助我们在进行混合式开发时, ...
- jquery和Js的区别和基础操作
jqery的语法和js的语法一样,算是把js升级了一下,这两种语法可以一起使用,只不过是用jqery更加方便 一个页面想要使用jqery的话,先要引入一下jqery包,jqery包从网上下一个就可以, ...
- 利用snowfall.jquery.js实现爱心满屏飞
小颖在上一篇一步一步教你用CSS画爱心中已经分享一种画爱心的方法,这次再分享一种方法用css画爱心,并利用snowfall.jquery.js实现爱心满屏飞的效果. 第一步: 利用伪元素before和 ...
- node.js学习(三)简单的node程序&&模块简单使用&&commonJS规范&&深入理解模块原理
一.一个简单的node程序 1.新建一个txt文件 2.修改后缀 修改之后会弹出这个,点击"是" 3.运行test.js 源文件 使用node.js运行之后的. 如果该路径下没有该 ...
- JS正则表达式常用总结
正则表达式的创建 JS正则表达式的创建有两种方式: new RegExp() 和 直接字面量. //使用RegExp对象创建 var regObj = new RegExp("(^\\s+) ...
- 干货分享:让你分分钟学会 JS 闭包
闭包,是 Javascript 比较重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,很难从定义去理解它.因此,本文不会对闭包的概念进行大篇幅描述 ...
- JS核心系列:理解 new 的运行机制
和其他高级语言一样 javascript 中也有 new 运算符,我们知道 new 运算符是用来实例化一个类,从而在内存中分配一个实例对象. 但在 javascript 中,万物皆对象,为什么还要通过 ...
随机推荐
- 【Java】学习路径44-多线程入门篇
这一章,我们学习线程的创建.线程的启动.线程的名字设置.线程的休眠.线程的加入.守护线程. 一个线程是一个单独的类的对象. 想让一个普通的类变成多线程,那么这个类需要继承Thread. 创建多线程的步 ...
- pytest精髓__fixture
命令:fixture(scope='function',params=None,autouse=False,ids=None,name=None) 参数说明 scope:有四个级别参数函数" ...
- KingbaseES V8R6C5集群部署启动securecmdd服务配置案例
案例说明: 对于KingbaseES V8R6C5版本在部集群时,需要建立kingbase.root用户在节点间的ssh互信,如果在生产环境禁用root用户ssh登录,则通过ssh部署会失败:在图形化 ...
- Spring集成测试
Spring 集成测试 需要再类的头部加入 @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"classpath ...
- 使用脚本在FTP上传、下载文件
由于最近勒索病毒变种又一次爆发,公司内部封锁了TCP 445端口.导致原来通过文件共享的方式上传下载的计划任务无法执行.所以,我开设了FTP服务器来完成这个工作. 关于如何建立FTP服务器,请看这里 ...
- k8s ingress-nginx 使用 snippet 添加自定义配置 (比如:新增请求头)
比如在有些时候我们需要在 server 里或者 location 里添加一些参数,例如添加包体大小限制.添加跨域配置.添加自定义header.处理响应header等等.遇到这些需求的时候,我们开始怀念 ...
- Elastic: 如何在阿里云上构建Elastic集群
- Alermanager_template,email
default.tmpl {{ define "__subject" }}[{{ .Status | toUpper }}{{ if eq .Status "firing ...
- ELK Stack 日志平台性能优化
转载自: https://mp.weixin.qq.com/s?__biz=MzAwNTM5Njk3Mw==&mid=2247487789&idx=1&sn=def0d8c2e ...
- 常见Content-Type(MIME)列表
Content-Type(MIME)用于标识发送或接收数据的类型,浏览器根据该参数来决定数据的打开方式.多用于指定一些客户端自定义的文件,以及一些媒体文件的打开方式. 文件扩展名 Content-Ty ...