JavaScript(JS)介绍
JavaScript ( JS ) 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言。虽然它是作为开发Web 页面的脚本语言而出名的,但是它也被用到了很多非浏览器环境中,例如 Node.js、 Apache CouchDB 和 Adobe Acrobat。JavaScript 是一种基于原型编程、多范式的动态脚本语言,并且支持面向对象、命令式和声明式(如函数式编程)风格。
JavaScript 的标准是 ECMAScript 。截至 2012 年,所有的现代浏览器都完整的支持 ECMAScript 5.1,旧版本的浏览器至少支持 ECMAScript 3 标准。2015年6月17日,ECMA国际组织发布了 ECMAScript 的第六版,该版本正式名称为 ECMAScript 2015,但通常被称为 ECMAScript 6 或者 ES6。自此,ECMAScript 每年发布一次新标准。本文档目前覆盖了最新 ECMAScript 的草案,也就是 ECMAScript2020。
JavaScript引入方式
script标签内写js代码
<script>
// js代码
</script>
引入外部js文件
<script src="myscript.js"></script>
JavaScript注释
就像 HTML 和 CSS,JavaScript 代码中也可以添加注释,浏览器会忽略它们,注释只是为你的同事(还有你,如果半年后再看自己写的代码你会说,这是什么垃圾玩意。)提供关于代码如何工作的指引。注释非常有用,而且应该经常使用,尤其在大型应用中。注释分为两类:
- 在双斜杠后添加单行注释,比如:
// 我是一条注释
- 在 /* 和 */ 之间添加多行注释,比如:
/*
我也是
一条注释
*/
JavaScript语言基础
声明变量
要想使用变量,你需要做的第一步就是创建它 -- 更准确的说,是声明一个变量。声明一个变量的语法是在 var 或 let 关键字之后加上这个变量的名字:
let name = 'xie';
var age = 18;
声明一个变量可以不立刻赋值,如果不初始化那么变量的值为undefined。
提示 : 在JavaScript中,所有代码指令都会以分号结尾 ;
— 如果忘记加分号,你的单行代码可能执行正常,但是在多行代码在一起的时候就可能出错。所以,最好是养成主动以分号作为代码结尾的习惯。
var 与 let 的区别
首先,如果你编写一个声明并初始化变量的多行 JavaScript 程序,你可以在初始化一个变量之后用 var 声明它,它仍然可以工作。 例如:
myName = 'Chris';
function logName() {
console.log(myName);
}
logName();
var myName;
这是由于变量的提升,更多细节请阅读变量提升。
但提升操作不再适用于 let 。如果将上面例子中的 var 替换成 let 将不起作用并引起一个错误。 这是一件好事——因为初始化后再声明一个变量会使代码变得混乱和难以理解。
其次,当你使用 var 时,可以根据需要多次声明相同名称的变量,但是 let 不能。let声明的变量修改值通过变量名 = 新值
修改。
变量命名规则
- 不要以下划线、数字开头
- 使用小写驼峰命名法
- 不要使用JavaScript保留字段,如var、function等。
- 变量名要见名知意
数据类型
Number
你可以在变量中存储数字,不论这些数字是像30(也叫整数)这样,或者像2.456这样的小数(也叫做浮点数)。与其他编程语言不同,在 JavaScript 中你不需要声明一个变量的类型。当你给一个变量数字赋值时,不需要用引号括起来。
let age = 18;
// 声明常量,无法修改
const pi = 3.14;
PS: NaN表示不是一个数字,但它是number类型。
常见的类型转换方法:
parseInt("123"); // 返回123
parseInt("ABC"); // 返回NaN,NaN属性是代表非数字值的特殊值。该属性用于指示某个值不是数字。
parseFloat("123.456"); // 返回123.456
String
字符串是文本的一部分。当你给一个变量赋值为字符串时,你需要用单引号或者双引号把值给包起来,否则JavaScript将会把这个字符串值理解成别的变量名。
let word = 'Long may the sunshine.';
length
获得字符串长度,length属性。
let name = 'xiezhongjing';
console.log(name.length);
indexOf
在字符串中查找子字符串所在的索引。
let name = 'xiezhongjing';
console.log(name.indexOf('j'));
slice
根据指定索引范围切割字符串。slice有两个参数,第一个为起始位置,第二个为结束位置(不包含),如果不传则是到原字符串结尾 。
let name = 'xiezhongjing';
console.log(name.slice(0,3));
toLowerCase 与 toUpperCase
字符串方法toLowerCase()和toUpperCase()字符串并将所有字符分别转换为小写或大写。
let name = 'A b C d';
name.toLowerCase();
name.toUpperCase();
replace
replace()方法将字符串中的一个子字符串替换为另一个子字符串。
let name = 'xie';
name.replace('x','s');
split
以给定的字符分割字符串,返回数组。
let name = 'xie|lin';
name.split('|'); // ['xie','lin']
Array
数组由方括号构成,其中包含用逗号分隔的元素列表。
let student = ['xie','lin','wang'];
// 索引访问数组
console.log(student[0]); // xie
// 索引修改数组值
student[0] = 'sie';
console.log(student); // ['sie','lin','wang']
length
length 属性可以获取数组的长度(数组中有多少项元素),这与查找字符串的长度(以字符为单位)完全相同 。
let a = [11,'22',33];
console.log(a.length); // 3
join
通过传递的字符串参数拼接数组中的字符串。
let a = ['11','22','33'];
a = a.join(',');
console.log(a) // 11,22,33;
push pop unshift shift
数组的添加和删除方法。
push()可以添加一个或多个元素到数组的末尾。
let myarr = [11,22,33];
myarr.push(44);
// myarr.push(44,55);
pop()删除数组的最后一个元素。
let myarr = [11,22,33];
myarr.pop();
unshift在头部插入元素,shift移除头部元素。
let myarr = [11,22,33];
myarr.unshift(44);
myarr.shift()
forEach
forEach方法功能强大,它能够遍历数组处理数组中的每个元素。forEach方法第一个参数为函数对象,此函数可以有三个参数,第一个为当前遍历的元素,index为当前索引,arr为元素所属数组对象。
let myarr = [11,22,33];
myarr.forEach((val,index,arr)=>{
console.log(val,index,arr)
})
map
map() 方法创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。
const array1 = [1, 4, 9, 16];
const map1 = array1.map(x => x * 2);
console.log(map1);
// [2, 8, 18, 32]
语法
let new_array = arr.map(function callback(currentValue[, index[, array]]) {
// 处理元素生成新数组
}[, thisArg])
参数
callback
currentValue
数组中正在处理的当前元素。index
可选
数组中正在处理的当前元素的索引。array
可选
map
方法调用的数组。
thisArg
可选
执行 callback
函数时值被用作this
。
Boolean
与python不同,javascript 布尔值为 true
和 false
。
在条件判断语句中,""(空字符串)、0、null
、undefined
、NaN
都是false
。
运算符
算数运算符
算术运算符是我们用来做和的基本运算符:
运算符 | 名称 | 作用 | 示例 |
+ | 加法 | 两个数相加。 | 6 + 9 |
- | 减法 | 从左边减去右边的数。 | 20 - 15 |
* | 乘法 | 两个数相乘。 | 3 * 7 |
/ | 除法 | 用右边的数除左边的数 | 10 / 5 |
% | 求余(有时候也叫取模) | 在你将左边的数分成同右边数字相同的若干整数部分后,返回剩下的余数 | 8 % 3 (返回 2,8除以3的倍数,余下2 。) |
** | 幂 | 取底数的指数次方,即指数所指定的底数相乘。它在EcmaScript 2016 中首次引入 | 5 ** 5 (返回 3125,相当于 5 * 5 * 5 * 5 * 5 。) |
自增和自减运算符
有时候,我们需要反复把一个变量加1或减1。 这可以方便地使用增量(++)和递减( -- )运算符来完成。
但是自增或自减运算符在变量两侧都能使用,并且它们的执行顺序不同。变量++会先赋值再进行自增1运算,而++变量会先进行自增运算再赋值!
let x = 10;
let res1 = x++;
let res2 = ++x;
console.log(res1,res2) // 10 12
赋值运算符
+=
、-=
、*=
、/=
比较运算符
运算符 | 名称 | 作用 | 示例 |
=== | 严格等于 | 测试左右值是否相同 | 5 === 2 + 4 |
!== | 严格不等于 | 测试左右值是否不相同 | 5 !== 2 + 3 |
> | 大于 | 测试左值是否大于右值 | 10 > 20 |
< | 小于 | 测试左值是否小于右值。 | 10 < 6 |
<= | 小于或等于 | 测试左值是否小于或等于右值。 | 3 <= 2 |
>= | 大于或等于 | 测试左值是否大于或等于正确值。 | 5 >= 4 |
PS: 在比较运算符中,==
在比较两个变量时会先进行类型转化再比较值是否相同,所以==
是不严格的。
流程控制
if - else
let a = 10;
if (a > 5){
console.log("yes");
} else {
console.log("no");
}
if - else if - else
let 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("...")
}
PS: switch中的case子句通常都会加break语句,否则程序会继续执行后续case中的语句。
for
for (let i=0;i<10;i++) {
console.log(i);
}
while
let i = 0;
while (i < 10) {
console.log(i);
i++;
}
三元运算
let a = 1;
let b = 2;
let c = a > b ? a : b
// 这里的三元运算顺序是先写判断条件a>b再写条件成立返回的值为a,条件不成立返回的值为b;三元运算可以嵌套使用;
let num1=10,num2=20;
let x=num1>num2 ?num1:(num2=="20")?num1:num2;
// x:10
函数
// 普通函数定义
function f1() {
console.log("Hello world!");
}
// 带参数的函数
function f2(a, b) {
console.log(arguments); // 内置的arguments对象,arguments相当于将出传入的参数全部包含
console.log(arguments.length);
console.log(a, b);
}
// 带返回值的函数
function sum(a, b){
return a + b;
}
sum(1, 2); // 调用函数
// 匿名函数方式 1
const sum = function(a, b){
return a + b;
}
sum(1,2);
// 匿名函数方式 2
const sum = (a,b) => a + b
sum(1, 2);
// 立即执行函数 书写立即执行的函数,首先先写两个括号()()这样防止书写混乱
(function(a, b){
return a + b;
})(1, 2);
内置对象
自定义对象
JavaScript的对象(Object)本质上是键值对的集合(Hash结构),但是只能用字符串作为键。
let obj = {"name": "xie", "age": 18};
console.log(ibj.name);
console.log(obj["age"]);
// 遍历对象
for(let key in obj){
console.log(key, obj[key]);
}
Date
创建Date对象
// 方法1:不指定参数
let d1 = new Date();
console.log(d1.toLocaleString());
// 方法2:参数为日期字符串
let d2 = new Date("2004/3/20 11:12");
console.log(d2.toLocaleString());
let d3 = new Date("04/03/20 11:12");
console.log(d3.toLocaleString());
// 方法3:参数为毫秒数
let d3 = new Date(5000);
console.log(d3.toLocaleString());
console.log(d3.toUTCString());
// 方法4:参数为年月日小时分钟秒毫秒
let d4 = new Date(2004,2,20,11,12,0,300);
console.log(d4.toLocaleString()); // 毫秒并不直接显示
Date对象方法
var d = new Date();
//getDate() 获取日
//getDay () 获取星期
//getMonth () 获取月(0-11)
//getFullYear () 获取完整年份
//getYear () 获取年
//getHours () 获取小时
//getMinutes () 获取分钟
//getSeconds () 获取秒
//getMilliseconds () 获取毫秒
//getTime () 返回自1970年1月1日(UTC)起经过的毫秒数
JSON
let json_str = '{"name": "xie", "age": 18}';
let obj = {"name": "xie", "age": 18};
// JSON字符串转换成对象
var new_obj = JSON.parse(json_str);
// 对象转换成JSON字符串
var new_json = JSON.stringify(obj);
RegExp
// 定义正则表达式两种方式
const reg1 = new RegExp("^[a-zA-Z][a-zA-Z0-9]{5,11}");
const reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/;
// 正则校验数据
reg1.test('xie1234');
reg2.test('xie1234');
/*第一个注意事项,正则表达式中不能有空格*/
// 全局匹配
const s1 = 'xie is cool';
s1.match(/s/);
s1.match(/i/g);
const reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/g;
reg2.test('xie123'); // true
reg2.test('xie123'); // false
reg2.lastIndex;
/*第二个注意事项,全局匹配时有一个lastIndex属性*/
// 校验不传参数时
var reg2 = /^[a-zA-Z][a-zA-Z0-9]{5,9}$/;
reg2.test();
reg2.test(undefined);
var reg3 = /undefined/;
reg3.test();