JavaScript

一. JavaScript概述

1. ECMAScript和JavaScript的关系

1996年11月,JavaScript的创造者--Netscape公司,决定将JavaScript提交给国际标准化组织ECMA,希望这门语言能够成为国际标准。次年,ECMA发布262号标准文件(ECMA-262)的第一版,规定了浏览器脚本语言的标准,并将这种语言称为ECMAScript,这个版本就是1.0版。

该标准一开始就是针对JavaScript语言制定的,但是没有称其为JavaScript,有两个方面的原因。一是商标,JavaScript本身已被Netscape注册为商标。而是想体现这门语言的制定者是ECMA,而不是Netscape,这样有利于保证这门语言的开发性和中立性。

因此ECMAScript和JavaScript的关系是,前者是后者的规格,后者是前者的一种实现。

2. ECMAScript的历史

年份 名称 描述
1997 ECMAScript 1 第一个版本
1998 ECMAScript 2 版本变更
1999 ECMAScript 3 添加正则表达式添加try/catch
ECMAScript 4 没有发布
2009 ECMAScript 5 添加"strict mode"严格模式添加JSON支持
2011 ECMAScript 5.1 版本变更
2015 ECMAScript 6 添加类和模块
2016 ECMAScript 7 增加指数运算符(**)增加Array.prototype.includes

注意:ES6就是指ECMAScript 6。

尽管 ECMAScript 是一个重要的标准,但它并不是 JavaScript 唯一的部分,当然,也不是唯一被标准化的部分。实际上,一个完整的 JavaScript 实现是由以下 3 个不同部分组成的:

  • 核心(ECMAScript)
  • 文档对象模型(DOM) Document object model (整合js,css,html)
  • 浏览器对象模型(BOM) Broswer object model(整合js和浏览器)

简单地说,ECMAScript 描述了JavaScript语言本身的相关内容。

JavaScript 是脚本语言
JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

JavaScript 很容易学习。

二. JavaScript2种引入方式

1. Script标签内写代码

2. 引入额外的JS文件

三. JavaScript语言规范

1. 注释(注释是代码之母)

// 这是单行注释

/*
多行注释1
多行注释2
多行注释3
*/

2. 结束符

JavaScript中的语句要以分号(;)为结束符。

四. JavaScript语言基础

1. 变量声明

声明变量的关键字: var

  • 变量的初始化: var x = 2;
  • 变量的声明: var y;
  • 变量的赋值: y = 2

2. 变量的命令规范

  • 1.必须使用字母, 下划线, $开始
  • 2.多个英文字母, 驼峰的表示: myName
  • 3.不能使用JS中关键字或保留字来进行命令
  • 4.严格区分大小写

3. 变量的5种基本数据类型

5种基本数据类型: number, string, boolean, undefined, null

打印数据类型: alert(声明的变量名);

查看属性类型: alert(typeof 声明的变量名);

  • Number 数值类型
    • 整数, 负数, 浮点数
  • String 字符串类型
    • 单引号或双引号表示方式
  • Boolean 布尔数据类型
    • 成立返回: true
    • 不成立返回: false
  • undefined 未定义的变量
    • alert打印返回值: undefined
    • alert+typeof打印数据类型返回值: undefined
  • null 空对象
    • alert打印返回值: null
    • alert+typeof打印数据类型返回值: object

4. ES6新增关键字let & const

ES6新增了let命令,用于声明变量。其用法类似于var,但是所声明的变量只在let命令所在的代码块内有效。例如:for循环的计数器就很适合使用let命令。

for (let i=0;i

ES6新增const用来声明常量。一旦声明,其值就不能改变。

const PI = 3.1415;
PI // 3.1415

PI = 3
// TypeError: "PI" is read-only

5. 使用var变量的声明被提前到作用域顶部,赋值则保留在原地(重点)

JS变量的声明被提前到作用域顶部,赋值保留在原地;(不要小看这句总结)请看下面这个例子:

var color = "blue";  
function getColor()  
{  
    console.log(color);   // undefined  
    var color = "red";  
    return color;  
}  
console.log(getColor());  // red  

可能你已经掌握了局部作用域会覆盖上一级作用域的同名变量。然后Line4的color先使用上一级作用域的color,所以误认为值是blue。其实不是,原因就在于,JS变量的声明(var修饰)会被提前到函数作用域的开始处,即相当于Line5的var color="red";被分解成var color; color="red";而var color先被JS引擎解析,覆盖了上一级的color,接着执行Line4的输出,此时color没有被赋值,赋值color="red";依然保留在Line5处。以上代码理解如下:

var color;  
color = "blue"
function getColor()  
{  
    var color;
    console.log(color);   // undefined  
    color = "red";  
    return color;  
}  
console.log(getColor());  // red  

这个细节,告诉我们,不能只知其一不知其二。特别是函数:

console.log(window.sum);
// 执行结果
/*
ƒ sum(a,b){
    return a+b;
}
*/

alert(sum(1,1));  // 2
function sum(a,b){
    return a+b;
}
console.log(window.sum);  // undefined
alert(sum(1,1));  // 报错
var sum = function (a,b){
    return a+b;
}

// 如下
var sum;
alert(sum(1,1));  // 报错
sum = function (a,b){
    return a+b;
}

总结: 在执行JS代码之前,所有的全局变量(包括函数和变量),都会绑定到window对象上,只是函数会包含函数体,变量仅仅是一个undefined。

6. let和var定义变量的区别(重点)

1. 作用域不一样,var是函数作用域,而let是块作用域,也就是说,在函数内声明了var,整个函数内都是有效的,比如说在for循环内定义了一个var变量,实际上其在for循环以外也是可以访问的,而let由于是块作用域,所以如果在块作用域内(比如说for循环内)定义的变量,在其外面是不可被访问的,所以let用在for (let i; i < n; i++)是一种很推荐的写法

2. let不能在定义之前访问该变量,但是var是可以得。也就是说,let必须是先定义,再使用,而var先使用后声明也行,只不过直接使用但是没有却没有定义的时候,其值为undefined,这块要注意,这一块很容易出问题,这也是个人认为的let比var更好的地方,至于为啥会有这种区别呢,实际上var有一个变量提升的过程。也就是说,当这个函数的作用域被创建的时候,实际上var定义的变量都会被创建,并且如果此时没有初始化的话,则默认会初始化一个undefined。

3. let不能被重新定义,但是var是可以的。这个呢,我个人认为,从规范化的角度来说,是更推荐的,比如说,你在前面声明了一个变量,后来写代码,因为忘了之前的代码逻辑,又声明了一个同名的变量,如果这俩变量逻辑不一样,并且后面都要用的话,很容易出问题,且不容易维护。

总之呢,let从规范化的角度来说,要比var要进步了很大一步。所以一般情况下的话,推荐用let,const这些。

let 和 const 命令深入: ES6 入门教程 

五. JavaScript数据类型

1. JavaScript拥有动态类型

/*
js/python是一门拥有动态类型的语言: 变量名指向一种类型以后可以更改
 但是有一些语言中,变量名之内指向一种后续不能更改.
*/
var xxx;              // 此时x是undefined
var xxx = 'jsaon';    // 此时的xxx是字符串
var xxx = 123;        // 此时的xxx是数值
var xxx = [1, 2, 3];  // 此时的xxx是数组

2. 数值(Number)

JavaScript不区分整型和浮点型,就只有一种数字类型。

var a = 11;
var b = 11.11;

// 如何查看当前数据类型?
console.log(typeof a);  // number
console.log(typeof b);  // number

// 特殊的 NaN:数值类型 表示的意思是“不是一个数字” NOT A NUMBER
console.log(typeof NaN); // number


// 类型转换
// python中int类型只能转换纯数字的字符串, float只能转换带一个点的纯数字的字符串
console.log(parseInt('123123'));             // 12312312
console.log(parseFloat('11.11'));            // 11.11
console.log(parseInt('11.11'));              // 11
console.log(parseInt('123sdasdajs2312d'));   // 123
console.log();parseInt('asdasdad123sdad');   // NaN

console.log(parseFloat('11'));           // 11
console.log(parseFloat('11.11'));        // 11.11
console.log(parseFloat('11.111faweff')); // 11.111
console.log(parseFloat('awefe11.11'));   // NaN


// 总结
/*
1. 数值类型: 纯数字, 浮点数, NaN
2. 查看类型: typeof
3. 字符串转换成数值类型: parseInt() parseFloat()
*/

3. 字符串(String)

基本用法:
var s = 'jason';
var s1 = 'tank';
// var s2 = '''alex'''  // 不支持三引号(抛出异常: VM665:1 Uncaught SyntaxError: Unexpected string)
console.log(typeof s1); // string

// 模版字符串(注意: 如果模板字符串中需要使用反引号,则在其前面要用反斜杠转义。)
var s3 = `
\`多行显示使用模版字符串
\`多行显示使用模版字符串
`;
console.log(typeof s3); // string

// 模版字符串除了可以定义多行文本之外还可以实现格式化字符串操作
var name = 'jason';
var age = 18;
var sss = `
My name is ${name} My age is ${age}`;
console.log(sss);  //  My name is jason My age is 18

// 书写${} 会自动去前面找大括号里面的变量名对应的值 如果没有定义直接报错
// var s4 = `my name is ${xxxxx}`;
// console.log(s4);  // 抛出异常: Uncaught ReferenceError: namemmmmm is not defined

// 字符串的拼接
/*
在python中不推荐你使用+做拼接 join
在js中推荐你直接使用+做拼接: python中字符串数值不能直接和字符串进行拼接, 但是再js中会把数值类型转换成字符串类型再进行拼接
*/
var sss1 = name + age;
console.log(sss1);  // jason18

// 总结
/*
1. python中使用三引号展示多行字符串. js中使用模板字符串展示多行字符串
2. python中使用%s,format,f"{}"等方式实现字符串的格式化. js中使用`${}`实现字符串的格式化
3. python中使用+,join实现字符串的拼接, +号数值不能直接和字符串进行拼接, join中列表中元素必须是字符串类型(推荐用join). 而js中使用+实现字符串的拼接,且当+号进行拼接时遇见数值类型会先换成字符串类型再进行拼接
*/
字符串类型常用方法:
功能 js python mysql 区别
返回长度 .length len() char_length()
移除两边空白 .trim() .strip() python中除了移除空白, 还可以指定要移除的字符, js只能单纯的移除空白
移除左边的空白 .trimLeft() .lstrip()
移除右边的空白 .trimRight() .rstrip()
返回第n个字符 .charAt(n) list[n]
拼接 .concat(value,…) .join(), + concat(), concat_ws(), group_concat() python中使用+,join实现字符串的拼接, +号数值不能直接和字符串进行拼接, join中列表中元素必须是字符串类型(推荐用join). 而js中使用+, 或者.concat()实现字符串的拼接,当进行拼接时遇见数值类型会先换成字符串类型再进行拼接
子序列位置 .indexOf(substring, start) .index(), rindex(), .find(), .rfind()
根据索引获取子序列 .substring(start , end) list[start, end, step] python中可以识别负数, js中substring不识别, 而slice则支持负数(推荐)
切片 .slice(start, end) list[start, end, step]
小写 .toLowerCase() .lower()
大写 .toupperCase(0 .upper()
分割 .split(delimiter, limit) .split(sep, maxsplit), rsplit(sep, maxsplit) python中第二个参数是限制分隔字符的个数, js中式获取切割之后的元素个数
var name = 'egonDSB';
console.log(name.length); // 7

var name1 = '   egonDSB  ';
console.log(name1.trim());      // egonDSB
console.log(name1.trimLeft());  // egonDSB
console.log(name1.trimRight()); //    egonDSB
var name2 = '$$jason$$';
console.log(name2.trim('$'));  // $$jason$$(不能加括号指定去除的内容)

console.log(name2.charAt(0));      // $

console.log(name2.indexOf('as'));  // 3

console.log(name2.substring(0,2));   // $$
console.log(name2.substring(0,-1));  // 不识别负数

console.log(name2.slice(0,-1));      // $$jason$

var name3 = 'eGoNDsb123666HahA';
console.log(name3.toUpperCase());  // EGONDSB123666HAHA
console.log(name3.toLowerCase());  // egondsb123666haha

var name4 = 'tank|hecha|liaomei|mengsao|...';
console.log(name4.split('|'));     // ["tank", "hecha", "liaomei", "mengsao", "..."]
console.log(name4.split('|', 2));  //  ["tank", "hecha"](第二个参数不是限制切割字符的个数还是获取切割之后元素的个数)


console.log(name.concat(name1, name2));  // egonDSB   egonDSB  $$jason$$
console.log(name+name1+name2);  // egonDSB   egonDSB  $$jason$$
var p = 1;
console.log(name.concat(p));  // egonDSB1*(js是弱类型, 内部会自动转换成相同的数据类型做操作)

// 总结
/*
.length  长度
.trim(), .trimLeft(), .trimRight() 只能移除空格没有参数
.substring(start, end), .slice(start, end) slice支持负数
.concat(val, ...), +
.indexOf(substring, start), .charAt(substring)
.toUpperCase(), toLowerCase()
.split(delimiter, limit) 第二个参数指定切分的个数, 不是次数
*/

4. 数值和字符串转换

数值转字符串:#

2种转换方式: 隐式转换, 调用.toString()方法

  • 隐式转换
    • 第一步: var num = 123;
    • 转换成字符串: var str = 123 + "abc";
  • 调用.toString()方法

    • 第一步: var num = 123;
    • 转换成字符串: var str = num.toString();
字符串转数值:

调用函数Number()方法

  • 字符串中不是全是数值类型的情况下: 报错, alert打印出现NaN: Not a number, 类型打印为number
    • 第一步: var str = 'abc';
    • 转换成数值: var num = Number(str);
  • 字符串中全是数字类型的情况: 正确转换
    • 第一步: var str = '123.123';
    • 转换成数值: var num = Number(str);

4. 布尔值(Boolean)

"""
1.在python中布尔值是首字母大写的
	True
	False
2.但是在js中布尔值是全小写的
	true
	false
# 布尔值是false的有哪些
	空字符串、0、null、undefined、NaN
"""
console.log(Boolean(0));         // false
console.log(Boolean(false));     // false
console.log(Boolean(undefined)); // false
console.log(Boolean(NaN));       // false
null和undefined:
  • null表示值是空,一般在需要指定或清空一个变量时才会使用,如 name=null;
  • undefined表示当声明一个变量但未初始化时,该变量的默认值是undefined。还有就是函数无明确的返回值时,返回的也是undefined。

null表示变量的值是空(null可以手动清空一个变量的值,使得该变量变为object类型,值为null),undefined则表示只声明了变量,但还没有赋值。

还不明白,上图吧!

JavaScript_第1张图片

JavaScript_第2张图片

六. 运算符

1. 算术运算符

/*
++表示自增1 类似于python中的 +=1
加号在前先加后赋值 加号在后先赋值后加
*/
var x = 10;
var res = x++;
console.log(res);  // 10
var res1 = ++x;
console.log(res1); // 12

2. 比较运算符

/*
==, != 弱等于  内部自动转换成相同的数据类型比较了
===, !== 强等于  内部不做类型转换
*/
console.log(1 == '1');   // true
console.log(1 === '1');  // false
console.log(1 != '1');   // false
console.log(1 !== '1');  // true

3. 逻辑运算符

/*
python中 and or not
js中      && ||  !
注意: 比较运算符返回的结果是布尔值, 逻辑运算返回的结果是短路运算以后的结果.
短路运算举例:
    0 && 1   返回结果是0. 也就是说0的布尔值为false, 与运算只要有一个结果是false那么结果就是false, 所以计算到0就不会往后计算了.
*/
console.log(5 && '5');   // '5'
console.log(0 || 1);     // 1
console.log(!5 && '5');  // false

4. 赋值运算符

  • 加法赋值运算符: +=
  • 减法赋值运算符: -=
  • 乘法赋值运算符: *=
  • 除法赋值运算符: /=
  • 取余赋值运算符: %=

七. 对象(Object): 数组

1. 数组对象的常用方法:

功能 js python 区别
数组的大小 .length len()
获取数组中的元素 array[index] list[index] python中支持负数, js中不支持负数索引
尾部追加元素 .push(ele) .append(ele)
弹出尾部的元素 .pop() .pop()
头部插入元素 .unshift(ele) .insert(0, ele), list[0]=ele
头部移除元素 .shift() .remove(头ele), pop(0), del list[0]
切片 .selice(start, end) list[start, end]
反转 .reverse() .reverse()
将数组元素连接成字符串 .join(seq) '.join() python中join中''中放的是连接的字符括号中放的是每个元素都是字符串类型的索引类型元素, 而js中点前面是数组后面是连接的字符.
连接数组 .concat(val, …) .extend, +
排序 .sort() .sort()
将数组的每个元素传递给回调函数 forEach(function(currentValue, index, arr), thisValue)
删除元素,并向数组添加新元素。 splice(index,howmany,item1,.....,itemX)
返回一个数组元素调用函数处理后的值的新数组 map(function(currentValue,index,arr), thisValue)
// 数组(类似于python里面的列表)	[]
var array1 = [222, 333, 444, 555];
console.log(typeof array1);  // object

console.log(array1[1]);   // 333
console.log(array1[-1]);  // undefined(不支持负数索引)

console.log(array1.push(666));  // 5
console.log(array1);  // [222, 333, 444, 555, 666]

console.log(array1.pop());  // 666
console.log(array1);  //  [222, 333, 444, 555]

console.log(array1.unshift(111));  // 5
console.log(array1);  // [111, 222, 333, 444, 555]

console.log(array1.shift(111));  // 111
console.log(array1);  // [222, 333, 444, 555]

console.log(array1.slice(0, -1));  // [222, 333, 444]
console.log(array1.slice(0, array1.length));  // [222, 333, 444, 555] (如果通过切片的方式复制一门数组对象, 结束位置指定-1是不行的, 这也只能取到数组的倒数第二个值, 因此我们要用.length属性)

console.log(array1.reverse());  // [555, 444, 333, 222]

console.log(array1.join('$'));  // 555$444$333$222

console.log(array1.concat(['aaa', 'bbb']));  // [555, 444, 333, 222, "aaa", "bbb"]
console.log(array1);  // [555, 444, 333, 222]

 2. forEach, map, seqlice

// forEach: forEach(function(currentValue, index, arr), thisValue)
// 1. 一个参数就是数组里面每一个元素对象
var array2 = [111, 222, 333, 444, 555];
array2.forEach(function (value) {
    console.log(value);
}, array2);
// 执行结果:
/*
111
222
333
444
555
666
 */

// 2. 两个参数就是元素 + 元素索引
array2.forEach(function (value, index) {
    console.log(value, index);
}, array2);
// 执行结果:
/*
111 0
222 1
333 2
444 3
555 4
666 5
 */

// 3. 元素 + 元素索引 + 元素的数据来源
array2.forEach(function (value, index, arr, xxx) {
    console.log(value, index, arr, xxx); // 最多三个. 基于js这种弱类型语言, 如果没有xxx传入也不会报错. 会抛出undefined
    // return [value, index, arr, xxx]; // 最多三个. 基于js这种弱类型语言, 如果没有xxx传入也不会报错. 会抛出undefined
}, array2);
// 执行结果:
/*
111 0 (6) [111, 222, 333, 444, 555, 666] undefined
222 1 (6) [111, 222, 333, 444, 555, 666] undefined
333 2 (6) [111, 222, 333, 444, 555, 666] undefined
444 3 (6) [111, 222, 333, 444, 555, 666] undefined
555 4 (6) [111, 222, 333, 444, 555, 666] undefined
666 5 (6) [111, 222, 333, 444, 555, 666] undefined
 */

// map: map(function(currentValue,index,arr), thisValue)
var array4 = [11, 22, 33, 44, 55];
array4.map(function (value) {
    console.log(value);
}, array4);
// 执行结果:
/*
11
22
33
44
55
66
 */

var res1 = array4.map(function (value, index) {
    return [value * 2, index]; // 如果相返回多个值, 必须被包含, 如果不包含返回的是逗号前的第一个值. 和python中只要逗号隔开返回元组不一样.
}, array4);
console.log(res1);  // [11, 22, 33, 44, 55]
// 执行结果:
/*
 [Array(2), Array(2), Array(2), Array(2), Array(2)]
0: (2) [22, 0]
1: (2) [44, 1]
2: (2) [66, 2]
3: (2) [88, 3]
4: (2) [110, 4]
length: 5
 */

var res2 = array4.map(function (value, index, arr) {
    return [value * 2, index*2, arr];
}, array4);
console.log(res2);  // [22, 44, 66, 88, 110]
// 执行结果:
/*
[Array(3), Array(3), Array(3), Array(3), Array(3)]
0: (3) [22, 0, Array(5)]
1: (3) [44, 2, Array(5)]
2: (3) [66, 4, Array(5)]
3: (3) [88, 6, Array(5)]
4: (3) [110, 8, Array(5)]
length: 5
 */

// splice: splice(index,howmany,item1,.....,itemX)
var array3 = [111, 222, 333, 444, 555];
array3.splice(0, 3);  // 两个参数 第一个是起始索引位置 第二个是删除的个数
console.log(array3);  // [444, 555]

array3.splice(0, 1, 666);  // 第三个参数 要添加到数组的新元素
console.log(array3);  // [666, 555]
array3.splice(0, 1, ['aaa', 'bbb']);
console.log(array3);
/*
[Array(2), 555]
0: (2) ["aaa", "bbb"]
1: 555
length: 2
*/

3. JS中Map和ForEach的区别

// 
/*
1. 能用forEach()做到的,map()同样可以。反过来也是如此。
2. map()会分配内存空间存储新数组并返回,forEach()方法不会返回执行结果,而是undefined. 也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
*/
var array5 = [11, 22, 33, 44, 55];
var aaa = array5.forEach(function (value) {
    return value;
});
var bbb = array5.map(function (value) {
    return value*2;
});
console.log(aaa);  //  undefined
console.log(bbb);  //  [11, 22, 33, 44, 55]

4. 总结

// 
/*
.length 长度
array[index] 索引取值(索引不能为负数)
.push(ele), .pop() 尾部追加/删除
.unshift(ele), .shift() 头部追加/删除
.slice(start, end) 切片(想实现复制end通过.length获取数组的长度, -1只能取到倒数第二个值)
.reverse() 反转
.join(seq) 拼接
.concat(val, ...) 连接数组(+号只能连接字符串)
.sort() 排序
.foreach(function(value,index,arr){}, thisValue) function是一个回调函数callback
.map(function(value,index,arr){}, thisValue)
.splice(index, removeCount, item1, ... , itemX)
*/

八. 流程控制

1. if判断

/*
注意: 在js中代码是没有缩进的, js中的`(条件){代码块}`替代了缩进, 以一下的缩进只是为了可读性, 而python是有缩进这么一说的.
*/
var age = 28;
// if
if (age>18){
  console.log('来啊 来啊')
}

// if-else
if (age>18){
  console.log('来啊 来啊')
}else{
  console.log('没钱 滚蛋')
}

// if-else if-else
if (age > 25){
    console.log('你好我们不合适!');
} else if (age < 18) {
    console.log('培养一下');
} else {
    console.log('我们在一起吧!');
}

2. switch语法: 提前列举好可能出现的条件和解决方式

switch中的case子句通常都会加break语句,否则程序会继续执行后续case中的语句

var num = 2;
switch (num) {
    case 0:  // case 条件: 条件=num成立执行
        console.log('吃');
        break; // 不加break 匹配到一个之后 就一直往下执行(简称: 穿透执行)
    case 1:
        console.log('喝');
        break;
    case 2:
        console.log('玩');  // 执行结果: 玩
        break;
    case 3:
        console.log('乐');
        break;
    default:
        console.log('条件都没有匹配上 默认走的流程');
}

3. for循环

// 1. for循环控制执行次数: 打印0-9数字
for (let i = 0; i < 10; i++) {
    console.log(i);
}

// 2. for循环遍历取值
for (let i in ['aaa', 'bbb', 'ccc']) {
    console.log(i);
}


// 3. for循环死循环之break和cointinue语句+死循环
let i = 0;
for (;;) {  // 死循环
    console.log('哈哈哈');
    if (i === 10000) {
        break;  // break跳出当前循环
    }
    // i ++;
    i += 1;
}

let sum = 0;   // 计算1~10数值, 并排除5这个数
for (let j = 1; j < 11; j++) {
    if (j === 10) {
        continue;  // continue跳出当前循环, 下次循环继续进行
    }
    sum += j;
    j += 1;
}
console.log(sum);   // 25

4. while循环: 打印1~100

var i = 1;
while (i < 101) {
    console.log(i);
    i += 1;
}

5. 三元表达式

/*
python中三元运算符 res = 条件成立返回的结果 if 条件 else 条件不成立返回的结果
JS中三元运算  res = 条件 ? 条件成立返回的结果:条件不成立返回的结果
*/
var res = 1 > 2 ? 2:8;
console.log(res); // 8
var res1 = 1 > 2 ? 2:(3 < !6 ? 1:0); // 三元运算符不要写的过于复杂
console.log(res1); // 0

6. 总结

/*
if (条件) {子代码块}
if (条件) {子代码块} else (条件) {子代码块}
if (条件) {子代码块} else if (条件) {子代码块} else (条件) {子代码块}

switch (参数) {
    case 条件: // 参数=条件则成立就执行以下代码块
        子代码块
        break;
    ...
    default:
        以上条件都没成立则指定这里的子代码块
}

for循环控制执行次数+遍历取值
    for (语句 1; 语句 2; 语句 3) {  // 循环控制执行次数
         要执行的代码块
    }
    语句 1 在循环(代码块)开始之前执行。
    语句 2 定义运行循环(代码块)的条件。
    语句 3 会在循环(代码块)每次被执行后执行。

    for (let i in 可遍历对象) {
        要执行的代码块
    }

while (条件) {
    子代码块
}

res = 条件 ? 条件成立返回的结果:条件不成立返回的结果
*/

九. 函数

1. 函数定义

/*
在python定义函数需要用到关键字def
在js中定义函数需要用到关键字function

语法: function 函数名(形参1,形参2,形参3...){函数体代码}
*/
// 无参函数
function func1() {
    console.log('hello world');
}
func1();  // hello world

// 有参函数
function func2(a, b) {
    console.log(a, b);
}
func2(1, 2); // 1 2
func2(1, 2, 3, 4, 5, 6, 7, 8, 9);  // 1 2(多了没关系 只要对应的数据)
func2(1); // 1 undefined(少了也没关系, 未定义的会用undefined填补)

2. 函数中的arguments参数: 能够获取到函数接受到的所有的参数

function func3(a, b, c) {
    console.log(arguments);
}
func3(1, 2, 3);
// 执行结果:
/*
Arguments(3) [1, 2, 3, callee: ƒ, Symbol(Symbol.iterator): ƒ]
0: 1
1: 2
2: 3
*/

// 使用arguments判断传参的确切性
function func4(a, b) {
    if (arguments.length < 2) {
        console.log('参数传少了!');
    } else if (arguments.length > 2) {
        console.log('参数传多了!');
    } else {
        console.log('正常执行');
    }
}
func4(1, 2, 3);  // 参数传多了!
func4(1);        // 参数传少了!
func4(1, 2);     // 正常执行

3. 函数的返回值: 使用的也是等同于python中的关键字return

function func5() {      // 返回一个值
    return 666
}
console.log(func5());  // 666

function func6(a, b) {  // 返回多个值, 多个值必须被包含不然就会返回逗号前面的那一个值.
    return a, b
}
console.log(func6(1, 2));  // 2

function func7(a, b) {
    return [a, b]
}
console.log(func7(1, 2));  // [1, 2]

4. 匿名函数: 就是没有名字

/*function () {
   console.log('哈哈哈');
}*/
let res = function() {  // 函数还可以被赋值, 对于匿名函数这也赋值虽然没有什么意义, 但是为了然函数能正常执行, 还是赋值一个变量吧~
   console.log('哈哈哈');
};
res();  // 哈哈哈

5. 箭头函数: 主要用来处理简单的业务逻辑 类似于python中的匿名函数

ES6中允许使用“箭头”(=>)定义函数

// 如果箭头函数不需要参数或需要多个参数,就是用圆括号代表参数部分
var f = () => 5;

// 等同于
var f = function(){return 5};

let func8 = v => v*2;  // 箭头左边的是形参 右边的是返回值
console.log(func8(2)); // 4

let func9 = function (v) {  // 上面与下面作用等同
    return v * 2;
};
console.log(func9(2)); // 4`

6. 总结

/*
函数定义: 无参, 有参
函数调用: 无参直接调用. 有参调用传值多余部分不要, 少的部分用undefined提补.
arguments: 可以接受所有参数, 可以通过arguments.length获取传入的参数个数.
函数返回值: 单个返回值.  多个返回值需被包含, 如果不包含只返回逗号前面一个值.
匿名函数: 匿名函数可被赋值.
箭头函数: 
    无参: let a = () => 返回值; 
    有参: let a = 形参 => 返回值; 
*/

十. 函数的全局变量和局部变量

1. 介绍

局部变量:
    在JavaScript函数内部声明的变量(使用 var)是局部变量,所以只能在函数内部访问它(该变量的作用域是函数内部)。只要函数运行完毕,本地变量就会被删除。

全局变量:
    在函数外声明的变量是全局变量,网页上的所有脚本和函数都能访问它。

变量生存周期:
    JavaScript变量的生命期从它们被声明的时间开始。
    局部变量会在函数运行以后被删除。
    全局变量会在页面关闭后被删除。

作用域
    首先在函数内部查找变量,找不到则到外层函数查找,逐步找到最外层。与python作用域关系查找一模一样

2. 示例

跟python查找变量的顺序一致

  • 示例1
var city = "BeiJing";
function f() {
  var city = "ShangHai";
  function inner(){
    var city = "ShenZhen";
    console.log(city);
  }
  inner();
}
f();  // 输出结果是?  ShenZhen

// ES6推荐使用let
let city = "BeiJing";
function f() {
  let city = "ShangHai";
  function inner(){
    let 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

// ES6推荐使用let
let city = "BeiJing";
function Bar() {
  console.log(city);
}
function f() {
  let city = "ShangHai";
  return Bar;
}
let 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

// ES6推荐使用let
let city = "BeiJing";
function f(){
    let city = "ShangHai";
    function inner(){
        console.log(city);
    }
    return inner;
}
let ret = f();
ret();   // ShangHai

十一. 内置对象和方法

JavaScript中的所有事物都是对象:字符串、数字、数组、日期,等等。在JavaScript中,对象是拥有属性和方法的数据。

我们在学习基本数据类型的时候已经带大家了解了,JavaScript中的Number对象、String对象、Array对象等。

注意: var s1 = "abc"和var s2 = new String("abc")的区别:typeof s1 --> string而 typeof s2 --> Object

JavaScript_第3张图片

1. 自定义对象 

JavaScript的对象(Object)本质上是键值对的集合(Hash结构),但是只能用字符串作为键。

// 你可以看成是我们python中的字典 但是js中的自定义对象要比python里面的字典操作起来更加的方便
// 创建自定义对象 {}
// 1. 第一种创建自定义对象的方式
let d1 = {'name': 'jason', 'age': 18};
console.log(typeof d1);   // object

console.log(d1['name']);  // jason(获取对象方式一)
console.log(d1.name);     // jason(获取对象方式二)

for (let i in d1) {
    console.log(i, d1[i]);  // 支持for循环 暴露给外界可以直接获取的也是键
}

// 2. 第二种创建自定义对象的方式:  需要使用关键字 new
let d2 = new Object();   // 创建的是空对象{}
d2.name = 'jason';   // 对象修改(增)方式一
d2['age'] = 18;      // 对象修改(增)方式二
console.log(d2);     // {name: "jason", age: 18}

// 总结:
/*
定义对象的2种方式: {}, new Object()
访问对象的2种方式: 对象.属性名, 对象['属性名']
修改对象的2种方式: 对象.属性名=属性值, 对象['属性名']=属性值
*/

ES6中提供了Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当做键。*

*也就是说,Object结构提供了“字符串--值”的对应,Map结构提供了“值--值”的对应,是一种更完善的Hash结构实现。

var m = new Map();
var o = {p: "Hello World"}

m.set(o, "content"}
m.get(o)  // "content"

m.has(o)     // true
m.delete(o)  // true
m.has(o)     // false

2. Date对象

// 自动获取当前时间
let d1 = new Date();
console.log(d1);  // Sun May 17 2020 00:27:39 GMT+0800 (中国标准时间)
console.log(d1.toLocaleString());  // 2020/5/17 上午12:28:34

// 自己手动输入时间
let d2 = new Date('2020/11/11 11:11:11');
console.log(d2);  // Wed Nov 11 2020 11:11:11 GMT+0800 (中国标准时间)
console.log(d2.toLocaleString());  // 2020/11/11 上午11:11:11

let d3 = new Date(2020,11,11,11,11,11);
console.log(d3);  // Fri Dec 11 2020 11:11:11 GMT+0800 (中国标准时间)
console.log(d3.toLocaleString());  // 2020/12/11 上午11:11:11(注意: 以上使用逗号隔开方式输入的时间的月份是从0开始 0-11月)

// 时间对象具体方法
let d4 = new Date('2020/5/17 0:28:34');
console.log(d4.getFullYear());  // 2020 (获取完整的年份)
console.log(d4.getMonth());     // 4 (获取月份0~11, 0代表1月, 11代表12月)
console.log(d4.getDate());      // 17 (获取日)
console.log(d4.getDay());       // 0 (获取星期0~6. 0代表星期日, 6代表星期六)
console.log(d4.getHours());       // 0 (小时. 如果时间小于10, 则显示个位数)
console.log(d4.getMinutes());   // 37 (获取分钟)
console.log(d4.getSeconds());   // 25 (获取秒)
console.log(d4.getMilliseconds());  // 588 (获取毫秒)
console.log(d4.getTime());      // 1589647045588 (时间戳)

// 总结:
/*
时间的2种显示格式:
    1. 默认: Sun May 17 2020 00:27:39 GMT+0800 (中国标准时间)
    2. 使用.toLocaleString()方法: 2020/5/17 上午12:28:34

时间的3种创建方式:
    1. 自动生成当前时间: new Date()
    2. 手动指定方式一: new Date('2020/5/17 12:28:34')
    3. 手动指定方式二: new Date(2020,5,17,12,28,34) 这种时间的指定当使用.toLocaleString()方法时月份范围是0~11

时间对象的具体方法:
    获取年完成年份    .getFullYear()
    获取月份(0~11)   .getMonth()
    获取日           .getDate()
    获取星期(0~6)    .getDay()
    获取小时         .getHours()
    获取分钟         .getMinutes()
    获取秒钟         .getSeconds()
    获取毫秒         .getMilliSeconds()
    获取时间戳        .getTime()
*/

练习:编写代码,将当前日期按“2017-12-27 11:11 星期三”格式输出。

function myDateFor() {
    let days = ['星期一', '星期二', '星期三', '星期四', '星期五', '星期六', '星期天'];
    let nowTime = new Date();
    let fullYear = nowTime.getFullYear();
    let month = nowTime.getMonth();
    let date = nowTime.getDate();
    let hours = nowTime.getHours();
    let minutes = nowTime.getMinutes();
    minutes = minutes < 10 ? '0'+minutes:minutes;
    let day = nowTime.getDay();
    day = days[day];
    month += 1;


    console.log(`${fullYear}-${month}-${date} ${hours}:${minutes} ${day}`);
}
myDateFor();

详细Date对象方法:点我

3. JSON对象

let obj = [11, 11.11, NaN, 'aaa', false, true, undefined, {}];
let serialize_obj = JSON.stringify(obj);
console.log(serialize_obj); // "[11,11.11,null,"aaa",false,true,null,{}] "  (序列化)

let deserialize_obj = JSON.parse(serialize_obj);
console.log(deserialize_obj); // [11, 11.11, null, "aaa", false, true, null, {…}]  (反序列化)

// 总结:
/*
在python中序列化反序列化
    dumps 		序列化
    loads		反序列化

在js中也有序列化反序列化
    JSON.stringify()	dumps
    JSON.parse()		loads
*/

4. RegExp对象

/*
在python中如果需要使用正则 需要借助于re模块
在js中需要你创建正则对象
*/
let sss = 'egondsb egondsb 1dsb dsb 111';
// 第一种开启正则方式: new RegExp('正则规则')
/*
.test():  接受一个字符串参数,在模式与该参数匹配的情况下返回true,否则返回false
.match(): 返回一个数组,数组中包含了匹配值,匹配值在源字符串首次出现的索引值,以及源字符串;
*/
let reg1 = new RegExp('[a-zA-Z][a-zA-Z0-9]{5,11}'); // 匹配字母,  加上5~11个字母或者数字
console.log(reg1.test(sss));   // true (正则校验数据)
console.log(sss.match(reg1));  // ["egondsb", index: 0, input: "egondsb egondsb 1dsb dsb 111", groups: undefined]

// 第二种开启正则方式: /正则规则/
let reg2 = /[a-zA-Z][a-zA-Z0-9]{5,11}/g;
console.log(reg2.test(sss));   //  true
console.log(sss.match(reg2));  // ["egondsb", "egondsb"]

// 缺陷一: 全局匹配模式的lastIndex与.test()效验数据(全局匹配时有一个lastIndex属性)
let reg3 = /^[a-zA-Z][a-zA-Z0-9]{5,11}/g;
console.log(reg3.test('egondsb'));  // true
console.log(reg3.test('egondsb'));  // false
console.log(reg3.test('egondsb'));  // true
console.log(reg3.test('egondsb'));  // false

console.log(reg3.lastIndex);  // 0
console.log(reg3.test('egondsb'));  // true
console.log(reg3.lastIndex);  // 7
console.log(reg3.test('egondsb'));  // false
console.log(reg3.lastIndex);  // 0

// 缺陷二: .test()效验时不传参 默认传的是undefined. 也能返回匹配成功true的信号.
let reg4 = /^[a-zA-Z][a-zA-Z0-9]{5,11}/;
console.log(reg4.test());  // true
console.log(reg4.test());  // true

let reg5 = /undefined/;
console.log(reg5.test('jason'));  // false
console.log(reg5.test());  // true
console.log(reg5.test(undefined));  // true


// 总结
/*
正则的2种开启方式: new RegExp('正则规则'), /正则规则/[g]
正则的效验: reg_obj.text(string)
正则的取值: string.match(reg_obj)  如果正则对象不是全局模式只能获取匹配到的第一个值
正则效验模式的2大缺陷:
    1. 全局模式下的lastIndex造成效验结果2极化; 匹配成功指针状态被保留到下一次, 导致下一次无法重新开始, 进而导致效验结果一会儿为false, 一会儿为true
    2. 效验模式不传参默认会传undefined, 导致在正常匹配中无undefined匹配规则情况下, 没有匹配内容, 默认输出结果为true.
*/

扩展阅读

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)      返回角的正切。

6. window对象

你可能感兴趣的:(前端,javascript,开发语言,ecmascript,python,前端)