JavaScript概述
引用1
函数 函数的定义 一般函数定义: function foo(a,b){ 函数的代码块; return 返回值 } 匿名函数: var bar = function(){...} 立即执行函数: (function(a,b){...})(实参1,实参2) 函数的参数: 不严谨(可传多,可传少,就是不报错) arguments:函数内部可以通过arguments拿到所有的参数 作用域 函数内部可以调用函数外部的变量 函数外部无法访问函数内部的变量 词法分析 函数调用的一瞬间要做两部: 1. 分析(AO对象) 1. 先分析有没有参数, 2. 看看有没有局部变量 3. 看看有没有函数声明 2. 真正执行 取值都是从AO对象上找 自定义对象 定义的两种方法: 1. var p1 = {name: "xiaoqiang", age: 38} 2. var p2 = new Object(); p2.name = "xiaoqiang" p2.age = 38; 遍历自定义对象方式: for (var i in p1){ console.log(i); console.log(p1[i]); } 内置对象和方法 1. Date 1. 生成对象 var d1 = new Date() var d2 = new Date("2018-03-13") 2. 方法: 1. d1.toLocalString() 2. d1.toUTCString() 3. d1.getFullYear() 4. d1.getMonth() (0~11) 5. d1.getDay() (星期天是0) 6. ... 2. JSON 1. 字符串转JSON对象 var jsonObj = JSON.parse('{"name": "xiaoqiang", "age": 18}') 2. JSON对象转成字符串 var s = JSON.stringify(jsonObj) 3. Math 1. 略... 4. RegExp 1. 定义正则两种方式 1. var reObj1 = new RegExp("^[a-zA-Z][a-zA-Z0-9]{5,11}$"); 2. var reObj2 = /^[a-zA-Z][a-zA-Z0-9]{5,11}$/ 2. 常用方法 reObj1.test("将要被校验的字符串") 3. 正则的匹配模式 1. g --> 全局 "Alexdashabi".replace(/a/g, "呵呵") 2. i --> 不区分大小写 "Alexdashabi".replace(/a/i, "呵呵") 4. 几个坑 1. 正则表达式之间不能加空格 2. .test()不传值相当于.test(undefined)--> .test("undefined") 3. 全局匹配模式注意事项 var reObj = /Alex/g; reObj.test("Alex") --> lastIndex属性被设置成下一位4 reObj.test("1234Alex") 就返回true
一、JS(JavaScript)
一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:
核心(ECMAScript)
文档对象模型(DOM) Document object model (整合js,css,html)
浏览器对象模型(BOM) Broswer object model(整合js和浏览器)
简单地说,ECMAScript 描述了JavaScript语言本身的相关内容。
JavaScript 是脚本语言,是一种轻量级的编程语言。
JavaScript 是可插入 HTML 页面的编程代码。
JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。
①注释: // 这是单行注释 /* 这是多行注释 */ ②结束符 JavaScript中的语句要以分号(;)为结束符。 ③变量声明 JavaScript的变量名可以使用_,数字,字母,$组成,不能以数字开头。 声明变量使用 var 变量名; 的格式来进行声明
var name = "Alex"; var age = 18;
④注意:
变量名是区分大小写的。
推荐使用驼峰式命名规则。
保留字不能用做变量名。
补充:
ES6新增了let命令,用于声明变量。其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效。例如:for循环的计数器就很适合使用let命令。
for (let i=0;i<arr.length;i++){...}
ES6新增const用来声明常量。一旦声明,其值就不能改变。
const PI = 3.1415; PI // 3.1415 PI = 3 // TypeError: "PI" is read-onl
二、引入JS的两种方式
1、Script标签内写代码
<script> // 在这里写你的JS代码 </script>
2、引入额外的JS文件
<script src="myscript.js"></script>
三、数据类型
JavaScript拥有动态类型
var x; // 此时x是undefined var x = 1; // 此时x是数字 var x = "Alex" // 此时x是字符串
1、数值
JavaScript不区分整型和浮点型,就只有一种数字类型。
var a = 12.34; var b = 20; var c = 123e5; // 12300000 var d = 123e-5; // 0.00123
还有一种NaN,表示不是一个数字(Not a Number)。
常用方法:
parseInt("123") // 返回123 parseInt("ABC") // 返回NaN,NaN属性是代表非数字值的特殊值。该属性用于指示某个值不是数字。 parseFloat("123.456") // 返回123.456
2、字符串
var a = "Hello" var b = "world; var c = a + b; console.log(c); // 得到Helloworld
拼接字符串一般使用“+”
var s="hello yuan"; //几个js方法示例 console.log(s.charAt(6)); // 返回指定位置的字符 y console.log(s.indexOf("h")); // 返回某个指定的字符串值在字符串中首次出现的位置 0 console.log(s.slice(2,-2)); // 从已有的数组中返回选定的元素,-2指从倒数第二个元素结束 llo yu console.log(s.slice(2)); // 没有指定从何处结束,切分的数组包含从 start 到数组结束的所有元素 llo yuan
string.slice(start, stop)和string.substring(start, stop): 两者的相同点: 如果start等于end,返回空字符串 如果stop参数省略,则取到字符串末 如果某个参数超过string的长度,这个参数会被替换为string的长度 substirng()的特点: 如果 start > stop ,start和stop将被交换 如果参数是负数或者不是数字,将会被0替换 silce()的特点: 如果 start > stop 不会交换两者 如果start小于0,则切割从字符串末尾往前数的第abs(start)个的字符开始(包括该位置的字符) 如果stop小于0,则切割在从字符串末尾往前数的第abs(stop)个字符结束(不包含该位置字符) slice和substring的区别
3、布尔值
区别于Python,true和false都是小写。
var a = true; var b = false;
""(空字符串)、0、null、undefined、NaN都是false
4、null和undefined
- null表示值是空,一般在需要指定或清空一个变量时才会使用,如 name=null;
- undefined表示当声明一个变量但未初始化时,该变量的默认值是undefined。还有就是函数无明确的返回值时,返回的也是undefined。
null表示变量的值是空,undefined则表示只声明了变量,但还没有赋值
5、数组
数组对象的作用是:使用单独的变量名来存储一系列的值。类似于Python中的列表
var a = [123, "ABC"]; console.log(a[1]); // 输出"ABC"
关于sort()需要注意:
如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
若 a 小于 b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
若 a 等于 b,则返回 0。
若 a 大于 b,则返回一个大于 0 的值。
示例:
function sortNumber(a,b){ return a - b } var arr1 = [11, 100, 22, 55, 33, 44] arr1.sort(sortNumber)
关于遍历数组中的元素,可以使用下面的方式:
var a = [10, 20, 30, 40]; for (var i=0;i<a.length;i++) { console.log(a[i]); }
6、foreach
7、splice
8、typeof类型查询
typeof是一个一元运算符(就像++,--,!,- 等一元运算符),不是一个函数,也不是一个语句。
四、运算符
1、算数运算符:+ - * / % ++ --
2、比较运算符:> >= < <= != == === !==
3、逻辑运算符:&& || !
4、赋值运算符:= += -= *= /=
五、流程控制
if-else
var a = 10; if (a > 5){ console.log("yes"); }else { console.log("no"); }
if-else if-else
var a = 10; if (a > 5){ console.log("a > 5"); }else if (a < 5) { console.log("a < 5"); }else { console.log("a = 5"); }
switch
var day = new Date().getDay(); switch (day) { case 0: console.log("Sunday"); break; case 1: console.log("Monday"); break; default: console.log("...") }
switch中的case子句通常都会加break语句,否则程序会继续执行后续case中的语句。
for
for (var i=0;i<10;i++) { console.log(i); }
while
var i = 0; while (i < 10) { console.log(i); i++; }
三元运算
var a = 1; var b = 2; var c = a > b ? a : b
python中的三元运算
六、函数
1、函数的定义
①带参函数
②带返回值的函数
③匿名函数
④立即执行函数
⑤箭头函数
2、函数中的arguments参数
3、函数的全局变量和局部变量
局部变量:
在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它(该变量的作用域是函数内部)。只要函数运行完毕,本地变量就会被删除。
全局变量:
在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。
作用域:
首先在函数内部查找变量,找不到则到外层函数查找,逐步找到最外层。与python作用域关系查找一模一样
几个例子:
1.
var city = "BeiJing"; function f() { var city = "ShangHai"; function inner(){ var city = "ShenZhen"; console.log(city); } inner(); } f(); //输出结果是?----------ShenZhen
2.
var city = "BeiJing"; function Bar() { console.log(city); } function f() { var city = "ShangHai"; return Bar; } var ret = f(); ret(); // 打印结果是?--------------BeiJing
3.闭包
var city = "BeiJing"; function f(){ var city = "ShangHai"; function inner(){ console.log(city); } return inner; } var ret = f(); ret(); // 打印结果是?---------------ShangHai
// 函数的定义 // function foo(a,b) { // console.log("a:", a); // console.log("b:", b); // return a+b; // } // 匿名函数 // var func = function (a, b) { // console.log("a:", a); // console.log("b:", b); // return a+b; // }; // 立即执行函数 // (function (a,b) { // console.log("立即执行函数"); // console.log(a+b); // var sss = "我是函数内部的变量"; // })(11,22); // console.log(sss); // 外部访问不到函数内部定义的变量(用立即执行函数防止变量污染全局变量) // console.log("立即执行函数"); // console.log(a+b); // var sss = "我是函数内部的变量"; console.log("==========================="); // 函数的调用 // var ret1 = foo(11,22,33,44,55); // var ret1 = foo(11); // 11+undefined --> NaN // console.log("a+b=", ret1); // var ret2 = func(11, 22); // console.log(ret2); // arguments // function func2(a,b) { // console.log("总共有" + arguments.length + "个参数"); // var ret = 0; // for (var i=0;i<arguments.length;i++){ // ret += arguments[i] // } // return ret; // } // // console.log(func2(11,22,33)); // JS中的词法分析 var age = 18; function func3(){ console.log(age); // 去AO找age var age = 22; // AO.age=undefined console.log(age); // function age() { // AO.age= function(){...} // console.log("xxxx"); // } } func3(); // 问:执行func3()之后的结果是? // 18 22 // 22 22 // 22 18 // 18 18 // null 22 // undefind 22 var age = 18; function foo(){ console.log(age); var age = 22; console.log(age); function age(){ console.log("呵呵"); } console.log(age); age(); } foo(); // 执行后的结果是? // 1. 先分析 给AO赋值 // var age = 22; --> AO.age=undefined; // function age(){console.log("呵呵");} --> AO.age=function(){...} // 2. 真正执行阶段 就去AO上找 // function(){...} // 22 // 22 // 总共三个值
4、词法分析
JavaScript中在调用函数的那一瞬间,会先进行词法分析。
词法分析的过程:
当函数调用的前一瞬间,会先形成一个激活对象:Avtive Object(AO),并会分析以下3个方面:
1:函数参数,如果有,则将此参数赋值给AO,且值为undefined。如果没有,则不做任何操作。
2:函数局部变量,如果AO上有同名的值,则不做任何操作。如果没有,则将此变量赋值给AO,并且值为undefined。
3:函数声明,如果AO上有,则会将AO上的对象覆盖。如果没有,则不做任何操作。
函数内部无论是使用参数还是使用局部变量都到AO上找。
例子:
//第一题 var age = 18; function foo(){ console.log(age); var age = 22; console.log(age); } foo(); // 问:执行foo()之后的结果是? //第二题: var age = 18; function foo(){ console.log(age); var age = 22; console.log(age); function age(){ console.log("呵呵"); } console.log(age); } foo(); // 执行后的结果是?
词法分析过程: 1、分析参数,有一个参数,形成一个 AO.age=undefine; 2、分析变量声明,有一个 var age, 发现 AO 上面已经有一个 AO.age,因此不做任何处理 3、分析函数声明,有一个 function age(){...} 声明, 则把原有的 age 覆盖成 AO.age=function(){...}; 最终,AO上的属性只有一个age,并且值为一个函数声明 执行过程: 注意:执行过程中所有的值都是从AO对象上去寻找 1、执行第一个 console.log(age) 时,此时的 AO.age 是一个函数,所以第一个输出的一个函数 2、这句 var age=22; 是对 AO.age 的属性赋值, 此时AO.age=22 ,所以在第二个输出的是 2 3、同理第三个输出的还是22, 因为中间再没有改变age值的语句了
七、内置对象和方法
1、自定义对象
2、date对象
getDate() 获取日 getDay () 获取星期 getMonth () 获取月(0-11) getFullYear () 获取完整年份 getYear () 获取年 getHours () 获取小时 getMinutes () 获取分钟 getSeconds () 获取秒 getMilliseconds () 获取毫秒 getTime () 返回累计毫秒数(从1970/1/1午夜)
作业:编写代码,将当前日期按‘2017-12-27 11:11 星期三’格式输出:
const WEEKMAP = { 0:"星期天", 1:"星期一", 2:"星期二", 3:"星期三", 4:"星期四", 5:"星期五", 6:"星期六" }; //定义一个数字与星期的对应关系对象 function showTime() { var d1 = new Date(); var year = d1.getFullYear(); var month = d1.getMonth() + 1; //注意月份是从0~11 var day = d1.getDate(); var hour = d1.getHours(); var minute = d1.getMinutes() < 10?"0"+d1.getMinutes():d1.getMinutes(); //三元运算 var week = WEEKMAP[d1.getDay()]; //星期是从0~6 var strTime = ` ${year}-${month}-${day} ${hour}:${minute} ${week} `; console.log(strTime) }; showTime(); 结果为: 2019-5-31 22:17 星期五
3、JSON对象
4、RegExp对象
//RegExp对象 //创建正则对象方式1 // 参数1 正则表达式(不能有空格) // 参数2 匹配模式:常用g(全局匹配;找到所有匹配,而不是在第一个匹配后停止)和i(忽略大小写) // 用户名只能是英文字母、数字和_,并且首字母必须是英文字母。长度最短不能少于6位 最长不能超过12位。 // 创建RegExp对象方式(逗号后面不要加空格) var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,11}$"); // 匹配响应的字符串 var s1 = "bc123"; //RegExp对象的test方法,测试一个字符串是否符合对应的正则规则,返回值是true或false。 reg1.test(s1); // true // 创建方式2 // /填写正则表达式/匹配模式(逗号后面不要加空格) var reg2 = /^[a-zA-Z][a-zA-Z0-9_]{5,11}$/; reg2.test(s1); // true // String对象与正则结合的4个方法 var s2 = "hello world"; s2.match(/o/g); // ["o", "o"] 查找字符串中 符合正则 的内容 s2.search(/h/g); // 0 查找字符串中符合正则表达式的内容位置 s2.split(/o/g); // ["hell", " w", "rld"] 按照正则表达式对字符串进行切割 s2.replace(/o/g, "s"); // "hells wsrld" 对字符串按照正则进行替换 // 关于匹配模式:g和i的简单示例 var s1 = "name:Alex age:18"; s1.replace(/a/, "哈哈哈"); // "n哈哈哈me:Alex age:18" s1.replace(/a/g, "哈哈哈"); // "n哈哈哈me:Alex 哈哈哈ge:18" 全局匹配 s1.replace(/a/gi, "哈哈哈"); // "n哈哈哈me:哈哈哈lex 哈哈哈ge:18" 不区分大小写 // 注意事项1: // 如果regExpObject带有全局标志g,test()函数不是从字符串的开头开始查找,而是从属性regExpObject.lastIndex所指定的索引处开始查找。 // 该属性值默认为0,所以第一次仍然是从字符串的开头查找。 // 当找到一个匹配时,test()函数会将regExpObject.lastIndex的值改为字符串中本次匹配内容的最后一个字符的下一个索引位置。 // 当再次执行test()函数时,将会从该索引位置处开始查找,从而找到下一个匹配。 // 因此,当我们使用test()函数执行了一次匹配之后,如果想要重新使用test()函数从头开始查找,则需要手动将regExpObject.lastIndex的值重置为 0。 // 如果test()函数再也找不到可以匹配的文本时,该函数会自动把regExpObject.lastIndex属性重置为 0。 var reg3 = /foo/g; // 此时 regex.lastIndex=0 reg3.test('foo'); // 返回true // 此时 regex.lastIndex=3 reg3.test('xxxfoo'); // 还是返回true // 所以我们在使用test()方法校验一个字符串是否完全匹配时,一定要加上^和$符号。 // 注意事项2(说出来你可能不信系列): // 当我们不加参数调用RegExpObj.test()方法时, 相当于执行RegExpObj.test("undefined"), 并且/undefined/.test()默认返回true。 var reg4 = /^undefined$/; reg4.test(); // 返回true reg4.test(undefined); // 返回true reg4.test("undefined"); // 返回true RegExp相关
5、math对象
abs(x) 返回数的绝对值。 exp(x) 返回 e 的指数。 floor(x) 对数进行下舍入。 log(x) 返回数的自然对数(底为e)。 max(x,y) 返回 x 和 y 中的最高值。 min(x,y) 返回 x 和 y 中的最低值。 pow(x,y) 返回 x 的 y 次幂。 random() 返回 0 ~ 1 之间的随机数。 round(x) 把数四舍五入为最接近的整数。 sin(x) 返回数的正弦。 sqrt(x) 返回数的平方根。 tan(x) 返回角的正切。 Math
// JS中自定义对象 // var person = {name: '小强', age: 38}; // 在JS的对象中,键(属性)默认不用加引号;并且自动把单引号转成双引号 // console.log(person); // // 单独取对象的属性 // console.log("name:", person.name); // console.log("age:", person.age); // // // 遍历对象的属性 // for (var i in person){ // console.log(i); // console.log(person[i]); // } // Date对象 var d1 = new Date(); console.log(d1); console.log(typeof d1); console.log(d1.toLocaleString()); // 转成字符串格式的本地时间 console.log(typeof d1.toLocaleString()); // 生成指定时间的Date对象 // var d2 = new Date("2004/3/20 11:12"); // console.log(d2.toLocaleString()); // 转成字符串格式的本地时间 // console.log(d2.toUTCString()); // 转成字符串格式的UTC时间 var d2 = new Date("2018-3-11 11:12"); console.log(d2.toLocaleString()); // 转成字符串格式的本地时间 console.log(d2.toUTCString()); // 转成字符串格式的UTC时间 console.log(d2.getDate()); // 获取那一天(多少号) console.log(d2.getDay()); // 获取星期几 console.log(d2.getMonth()); // 获取月份 console.log(d2.getFullYear()); // 获取年 console.log(d2.getHours()); // 获取小时 console.log(d2.getMinutes()); // 获取分钟 console.log(d2.getSeconds()); // 获取秒 console.log(d2.getTime()); // 获取时间戳 // JSON对象 console.log("=============================="); var s = '{"name": "xiaoqiang", "age": 38}'; // 把字符串转换成JS内部的对象 var ret = JSON.parse(s); console.log(ret); console.log(typeof ret); // 把JS内部的对象转换成字符串 var s2 = JSON.stringify(ret); console.log(s2); console.log(typeof s2); // RegExp对象 --> Python re模块 // 生产 RegExp对象 var reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9_]{5,11}$"); var regexpRet1 = reg1.test("xiaoqiang"); console.log(regexpRet1); var regexpRet2 = reg1.test("1xiaoqiang"); console.log(regexpRet2); console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test("xiaoqiang")); console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test("1xiaoqiang")); // 坑1 (正则表达式中间一定不可以有空格) console.log("============================================"); console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test("xiaoqiang")); console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test("1xiaoqiang")); // 坑2 // test()不传值相当于传了一个undefined进去 // 然后test()就把这个undefined当成是"undefined"来判断 console.log("============================================"); console.log(/^[a-zA-Z][a-zA-Z0-9_]{5,11}$/.test("undefined")); console.log(/^[0-9a-zA-Z][a-zA-Z0-9_]{5,11}$/.test()); console.log(/^[0-9][a-zA-Z0-9_]{5,11}$/.test(undefined)); console.log(/^[0-9][a-zA-Z0-9_]{5,11}$/.test("undefined")); // JS正则的两种模式 // 1. g 表示全局 // 2. i 忽略大小写 var ss = "Alexdashabi"; var s3 = ss.replace(/a/gi, "哈哈哈"); // 不是改变默认的字符串,而是生成了一个新的字符串 console.log(s3); // 坑3 // 当正则表达式使用了全局模式(g)的时候,并且你还让它去检测一个字符串,此时会引出来一个lastIndex // lastIndex会记住上一次匹配成功的位置,并把下一次要开始椒盐的位置记住 // console.log("==============================="); var r = /alex/g; console.log(r.test("alex")); // true console.log(r.lastIndex); // 4 console.log(r.test("alex")); // false console.log(r.lastIndex); console.log(r.test("alex")); // true console.log(r.lastIndex); console.log(r.test("alex")); // false