文章目录
参考文章
https://www.liaoxuefeng.com/wiki/1022910821149312/1023020745357888
菜鸟教程
维基百科
一、JavaScript
1、历史
要了解JavaScript,我们首先要回顾一下JavaScript的诞生。
在上个世纪的1995年,当时的网景公司正凭借其Navigator浏览器成为Web时代开启时最著名的第一代互联网公司。
由于网景公司希望能在静态HTML页面上添加一些动态效果,于是叫Brendan Eich这哥们在两周之内设计出了JavaScript语言。你没看错,这哥们只用了10天时间。
为什么起名叫JavaScript?原因是当时Java语言非常红火,所以网景公司希望借Java的名气来推广,但事实上JavaScript除了语法上有点像Java,其他部分基本上没啥关系。
2、简介
JavaScript ,通常缩写为 JS,是万维网的一种编程语言和核心技术,与 HTML 和 CSS 并驾齐驱。99%的网站在客户端使用JavaScript进行网页行为,通常包含第三方库。所有主要的 Web 浏览器都有一个专用的 JavaScript 引擎,用于在用户的设备上执行代码。
JavaScript 是一种高级的、通常是实时编译的语言,符合 ECMAScript 标准。它具有动态类型、基于原型的面向对象和一流的功能。它是多范式的,支持事件驱动的、函数式的和命令式的编程风格。它具有用于处理文本、日期、正则表达式、标准数据结构和文档对象模型 (DOM) 的应用程序编程接口 (API)。
ECMAScript 标准不包括任何输入/输出 (I/O),例如网络、存储或图形设施。在实践中,Web 浏览器或其他运行时系统为 I/O 提供 JavaScript API。
JavaScript 引擎最初仅用于 Web 浏览器,但现在已成为某些服务器和各种应用程序的核心组件。对于这种用法,最流行的运行时系统是 Node.js。
尽管 Java 和 JavaScript 在名称、语法和各自的标准库上相似,但这两种语言截然不同,并且在设计上有很大差异。JavaScript在语言设计上主要受到了Self(一种基于原型的编程语言)和Scheme(一门函数式编程语言)的影响,在语法结构上它和C语言很相似(如if条件语句、switch语句、while循环和do-while循环等)
JavaScript与Java在名字和语法上都很相似,但这两门编程语言从设计之初就有很大不同。JavaScript在语言设计上主要受到了Self(一种基于原型的编程语言)和Scheme(一门函数式编程语言)的影响,在语法结构上它和C语言很相似(如if条件语句、switch语句、while循环和do-while循环等)。
对于客户端来说,JavaScript通常被实现为一门解释语言,但如今它已经可以被即时编译(JIT)。随着HTML5和CSS3语言标准的推行,它还可以用于游戏、桌面和移动应用程序的开发,以及在服务器端网络环境运行(如Node.js)。
3、JScript的兴起
1996 年 11 月,Netscape 向 Ecma International 提交了 JavaScript,作为所有浏览器供应商都可以遵守的标准规范的起点。这导致了 1997 年 6 月第一个 ECMAScript 语言规范的正式发布。
标准过程持续了几年,1998 年 6 月发布了 ECMAScript 2,1999 年 12 月发布了ECMAScript 3。ECMAScript 4 的工作始于 2000 年。
与此同时,Microsoft浏览器市场占据了越来越大的主导地位。到 2000 年代初,Internet Explorer 的市场份额达到 95%。这意味着 JScript 成为 Web 上客户端脚本编写的事实标准。
Microsoft最初参与了标准过程,并用其JScript语言实现了一些建议,但最终它停止了在Ecma工作方面的合作。因此,ECMAScript 4 被封存了。
因为网景开发了JavaScript,一年后微软又模仿JavaScript开发了JScript,为了让JavaScript成为全球标准,几个公司联合ECMA(European Computer Manufacturers Association)组织定制了JavaScript语言的标准,被称为ECMAScript标准。
所以简单说来就是,ECMAScript是一种语言标准,而JavaScript是网景公司对ECMAScript标准的一种实现。
ECMAScript版本其实就是JavaScript 版本
4、JavaScript 中重要的AJAX
微软不正干,浏览器市场慢慢被抢一大半
2005年,Jesse James Garrett发布了一份白皮书,其中他创造了Ajax一词,并描述了一套技术,其中JavaScript是骨干,用于创建可以在后台加载数据的Web应用程序,避免了重新加载整页的需要。这引发了JavaScript的复兴时期,由开源库和围绕它们形成的社区带头。创建了许多新库,包括jQuery、Prototype、Dojo Toolkit和MooTools。
在 2000 年代初期 Internet Explorer 占主导地位的时期,客户端脚本停滞不前。这种情况在2004年开始改变,当时Netscape的继任者Mozilla发布了Firefox浏览器。Firefox受到许多人的欢迎,从Internet Explorer中占据了重要的市场份额。
谷歌于2008年首次推出Chrome浏览器,其V8 JavaScript引擎比竞争对手更快。关键的创新是及时编译(JIT),因此其他浏览器供应商需要为JIT彻底改革他们的引擎
2008年7月,这些不同的政党聚集在一起,在奥斯陆举行会议。这导致在2009年初达成了最终协议,将所有相关工作结合起来,推动语言向前发展。结果是2009年12月发布的ECMAScript 5标准。
二、ES6
1、ES历史
- 1996 年 11 月,Netscape 向 Ecma International 提交了 JavaScript,ECMAScript 1
- 1998 年 6 月发布了 ECMAScript 2。
- 1999 年 12 月发布了 ECMAScript 3。
- ECMAScript 4 的工作始于 2000 年。
- 2009 年 12 月发布的 ECMAScript 5 标准。(2008年7月,这些不同的政党在奥斯陆召开了一次会议。这导致了 2009 年初的最终协议,将所有相关工作结合起来并推动语言向前发展。)
- 2015 年发布了 ECMAScript 6 时正式确定了大量的补充和改进( ECMAScript 2015(ES2015))
ECMAScript 6.0(以下简称 ES6,ECMAScript 是一种由 Ecma国际(前身为欧洲计算机制造商协会,英文名称是EuropeanComputerManufacturersAssociation)通过ECMA-262标准化的脚本程序设计语言)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了,
并且 从 ECMAScript6开始,开始采用年号来做版本。即 ECMAScript2015,就是ECMAScript6。 它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。 每年一个新版本。
- 2016年6月 ECMAScript 2016(ES2016),第 7 版,多个新的概念和语言特性
- 2017年6月 ECMAScript 2017(ES2017),第 8 版,多个新的概念和语言特性
- 2018年6月 ECMAScript 2018 (ES2018),第 9 版,包含了异步循环,生成器,新的正则表达式特性和 rest/spread 语法。
- 2019年6月 ECMAScript 2019 (ES2019),第 10 版
- 2020年6月 ECMAScript 2020 (ES2020),第 11 版
- 2021年6月 ECMAScript 2021 (ES2021),第 12 版
- 2022年6月 ECMAScript 2022 (ES2022),第 13 版
2、ES6新特性
- 待编写
ECMAScript 2015(ES2015),第 6 版,最早被称作是 ECMAScript6(ES6),添加了类和模块的语法,其他特性包括迭代器,Python风格的生成器和生成器表达式,箭头函数,二进制数据,静态类型数组,集合(maps,sets和 weak maps)promise,reflection 和 proxies。作为最早的 ECMAScript Harmony版本,也被叫做ES6 Harmony。
1、let 声明变量
// var声明的变量往往会越域
// let声明的变量有严格局部作用域
{
var a = 1;
let b = 2;
}
console.log(a); // 1
console.log(b); // ReferenceError: b is not defined
// var可以声明多次
// let只能声明一次
var m = 1
var m = 2
let n = 3
// let n = 4
console.log(m) // 2
console.log(n) // Identifier 'n' has already been declared
// var会变量提升
// let不存在变量提升
console.log(x); // undefined
var x = 10;
console.log(y); //ReferenceError: y is not defined
let y = 20;
2、const 声明常量(只读变量)
// 1.声明之后不允许改变
// 2.一但声明必须初始化,否则会报错
const a = 1;
a = 3; //Uncaught TypeError: Assignment to constant variable.
3、解构表达式。数组解构,对象解构
数组
let arr = [1,2,3];
//以前我们想获取其中的值,只能通过角标。ES6可以这样:
const [x,y,z] = arr;// x,y,z将与arr中的每个位置对应来取值
//然后打印
console.log(x,y,z);
对象
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
//解构表达式获取值,将person里面每一个属性和左边对应赋值
const { name, age, language } = person;
//等价于下面
// const name = person.name;
// const age = person.age;
// const language = person.language;
//可以分别打印
console.log(name);
console.log(age);
console.log(language);
//扩展:如果想要将name的值赋值给其他变量,可以如下,nn是新的变量名
const { name: nn,age, language } = person;
console.log(nn);
console.log(age);
console.log(language);
4、字符串扩展几个新的 API
ES6为字符串扩展了几个新的API:-includes()
:返回布尔值,表示是否找到了参数字符串。-startsWith()
:返回布尔值,表示参数字符串是否在原字符串的头部。-endsWith()
:返回布尔值,表示参数字符串是否在原字符串的尾部。
let str = "hello.vue";
console.log(str.startsWith("hello"));//true
console.log(str.endsWith(".vue"));//true
console.log(str.includes("e"));//true
console.log(str.includes("hello"));//true
字符串模板
模板字符串相当于加强版的字符串,用反引号`,除了作为普通字符串,还可以用来定义多行
字符串,还可以在字符串中加入变量和表达式。
// 1、多行字符串
let ss = `
<div>
<span>hello world<span>
</div>
`
console.log(ss)
// 2、字符串插入变量和表达式。变量名写在${}中,${}中可以放
入JavaScript表达式。
let name = "张三";
let age = 18;
let info = `我是${na
// 3、字符串中调用函数
function fun() {
return "这是一个函数"
}
let sss = `O(∩_∩)O哈哈~,${fun()}`;
console.log(sss); // O(∩_∩)O哈哈~,这是一个函数
5、函数优化,
函数参数默认值
//在ES6以前,我们无法给一个函数参数设置默认值,只能采用变通写法:
function add(a, b) {
//判断b是否为空,为空就给默认值1
b = b || 1;
return a + b;
}
//传一个参数
console.log(add(10));
//现在可以这么写:直接给参数写上默认值,没传就会自动使用默认值
function add2(a ,b = 1) {
return a + b;
}
//传一个参数
console.log(add2(10))
2不定参数
不定参数用来表示不确定参数个数,形如,…变量名,由…加上一个具名参数标识符组成。
具名参数只能放在参数列表的最后,并且有且只有一个不定参数
unction fun(...values) {
console.log(values.length)
}
fun(1, 2) //2
fun(1, 2, 3, 4) //4
3箭头函数
ES6中定义函数的简写方式
一个参数
//以前声明一个方法
// var print = function (obj) {
// console.log(obj);
// }
//可以简写为:
var print = obj => console.log(obj);
//测试调用
print(100);
多个参数
//两个参数的情况:
var sum = function (a, b) {
return a + b;
}
//简写为:
//当只有一行语句,并且需要返回结果时,可以省略{} ,结果会自动返回。
var sum2 = (a, b)=> a + b;
//测试调用
console.log(sum2(10, 10));//20
//代码不止一行,可以用`{}`括起来
var sum3 = (a, b)=> {
c = a + b;
return c;
};
//测试调用
console.log(sum3(10, 20));//30
4 实战:箭头函数结合解构表达式
//需求,声明一个对象,hello方法需要对象的个别属性
//以前的方式:
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
function hello(person) {
console.log("hello," + person.name)
}
//现在的方式
var hello2 = ({ name }) => { console.log("hello," + name) };
//测试
hello2(person);
6、对象优化
1)、新增的 API
ES6 给 Object 拓展了许多新的方法,如
- keys(obj):获取对象的所有 key 形成的数组
- values(obj):获取对象的所有 value 形成的数组
- entries(obj):获取对象的所有 key 和 value 形成的二维数组。格式:
[[k1,v1],[k2,v2],...]
- assign(dest, …src) :将多个 src 对象的值 拷贝到 dest 中。(第一层为深拷贝,第二层为浅
拷贝)
const person = {
name: "jack",
age: 21,
language: ['java', 'js', 'css']
}
console.log(Object.keys(person));//["name", "age", "language"]
console.log(Object.values(person));//["jack", 21, Array(3)]
const target = { a: 1 };
const source1 = {b: 2 };
const source2 = {c: 3 };
//Object.assign方法的第一个参数是目标对象,后面的参数都是源对象。
Object.assign(target, source1, source2);
console.log(target)//{a: 1, b: 2, c: 3}
2)、声明对象简写
const age = 23
const name = "张三"
// 传统
const person1 = { age: age, name: name }
console.log(person1)
// ES6:属性名和属性值变量名一样,可以省略
const person2 = { age, name }
console.log(person2) //{age: 23, name: "张三"}
3)、对象的函数属性简写
let person = {
name: "jack",
//以前:
eat: function (food) {
console.log(this.name + "在吃" + food);
},
//箭头函数版:这里拿不到this
eat2: food => console.log(person.name + "在吃" + food),
//简写版:
eat3(food) {
console.log(this.name + "在吃" + food);
}
}
person.eat("apple");
4)、对象拓展运算符
拓展运算符(…)用于取出参数对象所有可遍历属性然后拷贝到当前对象。
// 1、拷贝对象(深拷贝)
let person1 = { name: "Amy", age: 15 }
let someone = { ...person1 }
console.log(someone) //{name: "Amy", age: 15}
// 2、合并对象
let age = { age: 15 }
let name = { name: "Amy" }
let person2 = { ...age, ...name } //如果两个对象的字段名重复,后面对象字
段值会覆盖前面对象的字段值
console.log(person2) //{age: 15, name: "Amy"}
7、map和reduce
map
map():接收一个函数,将原数组中的所有元素用这个函数处理后放入新数组返回。
let arr = ['1', '20', '-5', '3'];
console.log(arr)
arr = arr.map(s => parseInt(s));
console.log(arr)
reduce
语法:
arr.reduce(callback,[initialValue])
reduce为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元
素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调
用reduce的数组。
callback(执行数组中每个值的函数,包含四个参数)
1、previousValue(上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue(数组中当前被处理的元素)
3、index(当前元素在数组中的索引)
4、array(调用reduce的数组)
initialValue(作为第一次调用callback的第一个参数。)
const arr = [1,20,-5,3];
//没有初始值:
console.log(arr.reduce((a,b)=>a+b));//19
console.log(arr.reduce((a,b)=>a*b));//-300
//指定初始值:
console.log(arr.reduce((a,b)=>a+b,1));//20
console.log(arr.reduce((a,b)=>a*b,0));//-0
8、Promise
基础语法
const promise = new Promise(function (resolve, reject) {
//执行异步操作
if (/*异步操作成功*/) {
resolve(value);//调用resolve,代表Promise将返回成功的结果
} else {
reject(error);//调用reject,代表Promise会返回失败结果
}
});
使用箭头函数可以简写为:
const promise = new Promise((resolve, reject) => {
//执行异步操作
if (/*异步操作成功*/) {
resolve(value);//调用resolve,代表Promise将返回成功的结果
} else {
reject(error);//调用reject,代表Promise会返回失败结果
}
});
这样,在promise中就封装了一段异步执行的结果。
设置异步处理的结果
如果我们想要等待异步执行完成,做一些事情,我们可以通过promise的then方法来实现。
如果想要处理promise异步执行失败的事件,还可以跟上catch:
promise.then(function (value) {
//异步执行成功后的回调
}).catch(function (error) {
优化js的多条件连环操作
以前的方式
$.ajax({
url: "mock/user.json",
success(data) {
console.log("查询用户:", data);
$.ajax({
url: `mock/user_corse_${data.id}.json`,
success(data) {
console.log("查询到课程:", data);
$.ajax({
url: `mock/corse_score_${data.id}.json`,
success(data) {
console.log("查询到分数:", data);
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
}
});
},
error(error) {
console.log("出现异常了:" + error);
现在的Promise方式
new Promise((resolve, reject) => {
$.ajax({
url: "mock/user.json",
success(data) {
console.log("查询用户:", data);
resolve(data.id);
},
error(error) {
console.log("出现异常了:" + error);
}
});
}).then((userId) => {
return new Promise((resolve, reject) => {
$.ajax({
url: `mock/user_corse_${userId}.json`,
success(data) {
console.log("查询到课程:", data);
resolve(data.id);
},
error(error) {
console.log("出现异常了:" + error);
}
});
});
}).then((corseId) => {
console.log(corseId);
$.ajax({
url: `mock/corse_score_${corseId}.json`,
success(data) {
console.log("查询到分数:", data);
},
error(error) {
console.log("出现异常了:" + error);
}
});
});
再次封装公共方法优化的方式
let get = function (url, data) { //实际开发中会单独放到common.js中
return new Promise((resolve, reject) => {
$.ajax({
url: url,
type: "GET",
data: data,
success(result) {
resolve(result);
},
error(error) {
reject(error);
}
});
})
}
get("mock/user.json").then((result) => {
console.log("查询用户:", result);
return get(`mock/user_corse_${result.id}.json`);
}).then((result) => {
console.log("查询到课程:", result);
return get(`mock/corse_score_${result.id}.json`)
}).then((result) => {
console.log("查询到分数:", result);
}).catch(() => {
console.log("出现异常了:" + error);
});
9、模块化
模块化就是把代码进行拆分,方便重复利用。类似java中的导包:要使用一个包,必须先
导包。而JS中没有包的概念,换来的是模块。
模块功能主要由两个命令构成:export
和import
。
export
命令用于规定模块的对外接口。import
命令用于导入其他模块提供的功能。
export
比如我定义一个js文件:hello.js,里面有一个对象
const util = {
sum(a,b){
return a + b;
}
}
我可以使用export将这个对象导出:
const util = {
sum(a,b){
return a + b;
}
}
export {util};
当然,也可以简写为:
export const util = {
sum(a,b){
return a + b;
}
}
export
不仅可以导出对象,一切JS变量都可以导出。比如:基本类型变量、函数、数组、
对象。
当要导出多个值时,还可以简写。比如我有一个文件:user.js:
var name = "jack"
var age = 21
export {name,age}
省略名称
js提供了default
关键字,可以对导出的变量名进行省略
//无需声明对象的名字
export default {
sum(a,b){
return a + b;
}
}
import
使用export
命令定义了模块的对外接口以后,其他JS文件就可以通过import
命令加载这
个模块。
例如我要使用上面导出的util:
/导入util
import util from 'hello.js'
//调用util中的属性
util.sum(1,2)
//要批量导入前面导出的name和age:
import {name, age} from 'user.js'
console.log(name + " ,今年"+age +"岁了")
注意有点浏览器语法支持不全
三、js的个人练习题
- 输入年份 输入月份 判断该年的该月 有多少天?
- 1 3 5 7 8 10 12 不管哪一年都是31天
- 4 6 9 11 不管哪一年都是30天
- 只有2月不一样:
- 闰年:29
- 普通年:28
- 变量:年 月
- 判断条件:
- 1.能整除4且不能整除100 y%40 && y%100!=0
2.能整除400 y%4000
var year=Number(prompt("年份"));
var moth=Number(prompt("月份"));
switch(moth){
case 1:
case 3:
case 5:
case 7:
case 8:
case 10:
case 12:
alert("31天");
break;
case 4:
case 6:
case 9:
case 11:
alert("30天");
break;
case 2:
if(year%4==0&&year%100!=0&&year%400==0){
alert("29天");
}else{
alert("28天");
}
break;
}
-
张三为他的手机设定了自动拨号按1:拨爸爸的号按2:拨妈妈的号按3:拨爷爷的号 按4:拨奶奶的号
//注意事项: switch跟case的值的比较 是 全等=== 。
var hm=Number(prompt("请输号"));
switch(hm){
case 1:
alert("给老爸打");
break;
case 2:
alert("给妈妈打");
break;
case 3:
alert("给爷爷");
break;
default:
alert("你输入的无效");
break;
}
**
3.需求:已知公式:标准体重 = 身高 - 105; 上下浮动5公斤。
**
请实现一个计算器,用户输入身高体重,输出偏胖,偏瘦,标准。
var g=prompt("身高");
var z=prompt("体重:");
var bz=g-105;
var max=bz+5;
var min=bz-5;
if(z>max){
alert("偏重");
}else if(z<min){
alert("偏轻");
}else{
alert("体重标准");
}
4.个人所得税
个人所得税=(工资 - 三险一金-个税起征点)税率-速算扣除数
应纳税所得额=(工资 - 三险一金 - 个税起征点)
输入工资;
工资不超过 7662 那么五险一金就按照工资20%计算超过 7662 五险一金就按照 7662*20%
全月应纳税所得额 税率 速算扣除数(元)
全月应纳税额不超过1500元 3% 0
全月应纳税额超过1500元至4500元 10% 105
全月应纳税额超过4500元至9000元 20% 555
全月应纳税额超过9000元至35000元 25% 1005
全月应纳税额超过35000元至55000元 30% 2755
全月应纳税额超过55000元至80000元 35% 5505
全月应纳税额超过80000元 45%
13505
<script type="text/javascript">
var gz=Number(prompt("工资是多少"));
var s;//三险一金
var yn;//应纳税所得额
var gr;//个人所得税
if(gz<7662){
s=gz*0.2;
}else{
s=7662*0.2;
}
yn=gz-s-3500;
if(yn<=0){
alert("不好意思你没有资格交税");
}else if(yn>0){
gr=yn*0.03;
}else if(yn>1500 && yn<=4500){
gr=yn*0.1-105;
}else if(yn>4500 && yn<=9000){
gr=yn*0.2-555;
}else if(yn>9000 && yn<=35000){
gr=yn*0.25-1005;
}else if(yn>35000 && yn<=55000){
gr=yn*0.3-2755;
}else if(yn>55000 && yn<=80000){
gr=yn*0.45-555;
}
alert("你应该缴纳的个人所得税"+gr);
</script>
5.循环
需求:迟到了,罚你写10000遍,我错了,我再也不迟到了!
循环需要哪些内容:
条件:
变量 变化在100次的范围;可以0-99 1-100 200-199
初始值
最大值
代码块:
document.write(“我错了,我再也不迟到了!”)
初始变量的自增
综上所述:循环必须四个条件:
1.初始化变量
2.循环条件
3.循环代码块
4.初始化变量的重新赋值,如果没有就会造成死循环。
计算1-100之和
var i=1;
var sum=0;
while(i<101){
sum+=i;
i++;
}
alert("和:"+sum);
var sum=0;
for(var i=1;i<101;i++){
sum+=i;
}
alert(sum);