一、JS初步
JavaScript 是属于 HTML 和 Web 的编程语言。
JS能够做什么呢?
JavaScript 能够改变 HTML 内容
JavaScript 能够改变 HTML 属性
JavaScript 能够改变 CSS 样式
JavaScript 能够隐藏 HTML 元素
JavaScript 能够显示隐藏的 HTML 元素
运行JavaScript有多种方式,可以直接在浏览器的控制台编写运行;也可以编写一个独立的js文件,然后在Html文件中引入,(这两种方法由浏览器解释执行,是以前唯一的方式)。也可以用编辑软件如Webstrom或VSCode编写独立的js文件,由安装好的Node.js解释执行运行。(Node.js下载)
两个版本都可以用,我下的是18.4.0
二、基本语法
- 标识符
所谓标识符,就是指变量、函数、属性的名字,或者函数的参数。标识符可以是按照下列格式规则组合起来的一或多个字符:第一个字符只能是字母、下划线( _ )或美元符号( $ )之一;其他字符可以是字母、下划线、美元符号或数字。按照惯例,ECMAScript(European Computer Manufacturers Association) 标识符采用 驼峰大小写格式,也就是第一个字母小写,剩下的每个单词的首字母大写,如getNameById。
所有 JavaScript 变量必须以唯一的名称的标识。
这些唯一的名称称为标识符。
标识符可以是短名称(比如 x 和 y),或者更具描述性的名称(age、sum、totalVolume)。
构造变量名称(唯一标识符)的通用规则是:
名称可包含字母、数字、下划线和美元符号
名称必须以字母开头
名称也可以 $ 和 _ 开头(但是在本教程中我们不会这么做)
名称对大小写敏感(y 和 Y 是不同的变量)
保留字(比如 JavaScript 的关键词)无法用作变量名称
- 语句
语句后面的;
建议添加,但不是必须
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript 语句</h2>
<p><b>JavaScript 程序</b> 是一系列由计算机执行的 <b>语句</b>。</p>
<p id="demo"></p>
<script>
var x, y, z; // 语句 1
x = 22; // 语句 2
y = 11; // 语句 3
z = x + y; // 语句 4
document.getElementById("demo").innerHTML =
"z 的值是" + z + "。";
</script>
</body>
</html>
3. 数字
写数字有无小数点均可
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript 数值</h2>
<p>写数值有无小数点均可。</p>
<p id="demo"></p>
<script>
document.getElementById("demo").innerHTML = 15.90;
</script>
</body>
</html>
4. 注释
JavaScript 注释用于解释 JavaScript 代码,增强其可读性。
JavaScript 注释也可以用于在测试替代代码时阻止执行。
单行注释
单行注释以 // 开头。
任何位于 // 与行末之间的文本都会被 JavaScript 忽略(不会执行)。
<!DOCTYPE html>
<html>
<body>
<h1 id="myH"></h1>
<p id="myP"></p>
<script>
// 改变标题:
document.getElementById("myH").innerHTML = "JavaScript 注释";
// 改变段落:
document.getElementById("myP").innerHTML = "我的第一个段落。";
</script>
</body>
</html>
句末注释
var x = 5; // 声明 x,为其赋值 5
var y = x + 2; // 声明 y,为其赋值 x + 2
多行注释
多行注释以 /* 开头,以 / 结尾。
任何位于 / 和 */ 之间的文本都会被 JavaScript 忽略。(快捷:鼠标选中,加上ctrl+/
)
- 变量
JavaScript 变量是存储数据值的容器。
ECMAScript 的变量是松散类型的,所谓松散类型就是可以用来保存任何类型(如: String、Number、Boolean以及Object等)的数据。换句话说,每个变量仅仅是一个用于保存值的占位符而已。定义变量时要使用 var 操作符,后跟变量名(即一个标识符),如下所示: var message; 这行代码定义了一个名为 message 的变量,该变量可以用来保存任何值。
有一点必须注意,即用 var 操作符定义的变量将成为定义该变量的作用域中的局部变量。也就是说,如果在函数中使用 var 定义一个变量,那么这个变量在函数退出后就会被销毁。
var x = 7;
var y = 8;
var z = x + y;
本例中:
x 存储值 7
y 存储值 8
z 存储值 15
二、操作符
一元操作符 ++ --
布尔操作符 && || !
算数运算符
例子:
var result = 5 + '5'; // 一个数值和一个字符串相加
console.log(result); // '55'
//============================================
var num1 = 5;
var num2 = 10;
var message = "The sum of 5 and 10 is " + num1 + num2;// (num1 + num2),还可使用模板字符串``
console.log(message); // "The sum of 5 and 10 is 510"
关系运算符<> <=>= == === != !==
===称为全等(包括值和类型)
var x = 5;//将数字5赋给x
console.log(x == 5);//输出数字5
console.log(x == '5');//输出字符‘5’
console.log(x === 5);//输出数字5和他的类型
console.log(x === '5');
条件操作符? :
var max = (num1 > num2) ? num1 : num2;
三、语句
if do-while while for for-in for-of break continue switch
var colors = ['red', 'green', 'blue', 'brown']; //colors是一个数组
//传统遍历(基本不用了)
for(var i=0;i<colors.length;i++){
console.log(colors[i]);
}
//for-in,专注下标
for(var c in colors){
console.log(colors[c]);
}
//for-of,专注元素
for(var c of colors){
console.log(c);
}
//高级遍历
colors.forEach(c => console.log(c));
var other = colors.map(c => c + 'X');//map不仅遍历,还返回另一个数组
console.log(other);
四、函数
JavaScript 函数是被设计为执行特定任务的代码块。
JavaScript 函数会在某代码调用它时被执行。
例如:
function myFunction(p1, p2) {
return p1 * p2; // 该函数返回 p1 和 p2 的乘积
}
4.1 函数语法
JavaScript 函数通过 function 关键词进行定义,其后是函数名和括号 ()。
函数名可包含字母、数字、下划线和美元符号(规则与变量名相同)。
圆括号可包括由逗号分隔的参数:(参数 1, 参数 2, ...)
由函数执行的代码被放置在花括号中:{}
function name(参数 1, 参数 2, 参数 3) {
要执行的代码
}
函数参数(Function parameters)是在函数定义中所列的名称。
函数参数(Function arguments)是当调用函数时由函数接收的真实的值。
在函数中,参数是局部变量。
4.2 函数调用
函数中的代码将在其他代码调用该函数时执行:
当事件发生时(当用户点击按钮时)
当 JavaScript 代码调用时
自动的(自调用)
4.3 函数返回
当 JavaScript 到达 return 语句,函数将停止执行。
如果函数被某条语句调用,JavaScript 将在调用语句之后“返回”执行代码。
函数通常会计算出返回值。这个返回值会返回给调用者:
var x = myFunction(7, 8); // 调用函数,返回值被赋值给 x
function myFunction(a, b) {
return a * b; // 函数返回 a 和 b 的乘积
}
x返回的结果是:56
ECMAScript 函数不介意传递进来多少个参数,也不在乎传进来参数是什么数据类型。
也就是说,即便你定义的函数只接收两个参数,在调用这个函数时也未必一定要传递两个参数。可以传递一个、三个甚至不传递参数,而解析器永远不会有什么怨言。
之所以会这样,原因是 ECMAScript 中的参数在内部是用一个数组来表示的。函数接收到的始终都是这个数组,而不关心数组中包含哪些参数(如果有参数的话)。如果这个数组中不包含任何元素,无所谓;如果包含多个元素,也没有问题。
如果在 ECMAScript中定义了两个名字相同的函数,则该名字只属于后定义的函数。请看下面的例子:
function addSomeNumber(num){
return num + 100;
}
function addSomeNumber(num) {
return num + 200;
}
console.log(addSomeNumber(100)); //300
五、 对象(Object)
对象 Object 是JS中使用最多的一个类型。通常将数据和方法封装在对象中。可以这么说在JS中万物皆为对象。
字符串也可以是一个对象
日期是一个对象
数学和正则表达式也是对象
数组是一个对象
函数也可以是对象
对象是变量的容器;写法以键值对的方式(键名:键值);键值对称之为对象的属性;循环对象一般用 for in
// 对象定义
let person = {
firstName:"ouyang",
lastName:"xiu",
age:18
};
// 循环对象
for(let key in person){
console.log(key); // 键名
console.log(person[key]) // 键值
}
六、 数组Array
除了 Object 之外, Array 类型算是 JS 中最常用的类型了。
JS 中的数组与其他多数语言中的数组有着相当大的区别。虽然JS 数组与其他语言中的数组都是数据的有序列表,但与其他语言不同的是,JS 数组的每一项 可以保存任何类型的数据(不建议!
)。
也就是说,可以用数组的第一个位置来保存字符串,用第二位置来保存数值,用第三个位置来保存对象,以此类推。而且,JS 数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。
创建数组一般有两种方式:(new和自变量
)
//方式一new
var colors = new Array('red', 'blue', 'green');
//方式二字面量
var colors = ['red', 'blue', 'green']; // 创建一个包含 3 个字符串的数组
console.log(colors[1]);
colors[3] = 'brown';
console.log(colors.length);
var names = []; // 创建一个空数组
var hyBird = [1, 2, 'haha', {firstName: 'Yong', lastName: 'Wang'}]; //不推荐!
console.log(hyBird[3].firstName);
常用的数组方法:
1 元素结合
var colors = ['red', 'green', 'blue'];
console.log(colors.join(',')); //red,green,blue
console.log(colors.join('||')); //red||green||blue
2 堆栈方法
栈是一种 LIFO(Last-In-First-Out,后进先出)的数据结构,也就是最新添加的项最早被移除。而栈中项的插入(叫做推入)和移除(叫做弹出),只发生在一个位置——栈的顶部。JS 为数组专门提供了 push()
和 pop()
方法,以便实现类似栈的行为。
var colors = []; // 创建一个数组
var count = colors.push('red', 'green'); // 末尾推入两项
console.log(count); //2
colors.push('black'); // 末尾推入另一项
console.log(colors); //3
var item = colors.pop(); // 末尾弹出最后一项
console.log(item); //'black'
console.log(colors); //2
3 队列方法
栈数据结构的访问规则是 LIFO(后进先出),而队列数据结构的访问规则是 FIFO(First-In-First-Out,先进先出)。队列在列表的末端添加项,从列表的前端移除项。由于 push()
是向数组末端添加项的方法,因此要模拟队列只需一个从数组前端取得项的方法。实现这一操作的数组方法就是 shift()
,它能够移除数组中的第一个项并返回该项,同时将数组长度减1。
var colors = new Array(); //创建一个数组
colors.push('red', 'green'); //推入两项
console.log(colors); //2
count = colors.push('black'); //推入另一项
console.log(colors); //3
var item = colors.shift(); // 前端弹出第一项
console.log(item); //'red'
console.log(colors);
push、pop操作在数组末,而 unshift、shift操作在数组头;push、unshift压入而pop、shift弹出。
4 反转数组项
简而言之就是将数组中元素逆序
var values = [1, 2, 3, 4, 5];
values.reverse();
console.log(values); //5,4,3,2,1
5 链接方法
var colors1 = ['red', 'green', 'blue'];
var colors2 = ['yellow', 'black'];
console.log(colors1.concat(colors2));
console.log(colors2.concat(colors1));
console.log(colors2.concat('brown'));
console.log(color2)//注意:concat返回一个新数组,原数组没改变
6 分片方法
slice() ,它能够基于当前数组中的一或多个项创建一个新数组。 slice() 方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice() 方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
slice() 方法不会影响原始数组。
7 splice方法
该方法将会直接更改原始数组
它可以对数组执行如下操作
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数) 和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。
替换:以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。
var colors = ['red', 'green', 'blue'];
var removed = colors.splice(0,1); // 删除第一项
console.log(colors); // green,blue
console.log(removed); // red,返回的数组中只包含一项
removed = colors.splice(1, 0, 'yellow', 'orange'); // 从位置 1 开始插入两项
console.log(colors); // green,yellow,orange,blue
console.log(removed); // 返回的是一个空数组
removed = colors.splice(1, 1, 'red', 'purple'); // 插入两项,删除一项
console.log(colors); // green,red,purple,orange,blue
console.log(removed); // yellow,返回的数组中只包含一项
七、链式语法
发展到现在,链式语法已经变得非常的流行了,这野一种很容易实现的模式。只需要让每个函数返回 this代表包含该函数的对象,这样其他函数就可以立即被调用。
//链式语法
var bird = {//定义对象字面量
catapult: function() {
console.log( 'Yippeeeeee!' );
return this;//返回bird对象自身
},
destroy: function() {
console.log( "That'll teach you... you dirty pig!" );
return this;
}
};
bird.catapult().destroy();
八、闭包
闭包是什么?闭包是Closure,这是静态语言所不具有的一个新特性。但是闭包也不是什么复杂到不可理解的东西,简而言之,闭包就是:
函数的局部变量集合,只是这些局部变量在函数返回后会继续存在。
闭包就是就是函数的“堆栈”在函数返回后并不释放,我们也可以理解为这些函数堆栈并不在栈上分配而是在堆上分配
当在一个函数内定义另外一个函数就会产生闭包。
九、补充一些额外的知识点
9.1 Canvas
canvas
是 HTML5 新增的,一个可以使用脚本(通常为JavaScript)在其中绘制图像的 HTML 元素。它可以用来制作照片集或者制作简单(也不是那么简单)的动画,甚至可以进行实时视频处理和渲染。
Canvas
是由HTML代码配合高度和宽度属性而定义出的可绘制区域。JavaScript代码可以访问该区域,类似于其他通用的二维API,通过一套完整的绘图函数来动态生成图形。
例如画一条直线:
<!DOCTYPE html>
<html>
<head>
<title>Canvas</title>
</head>
<body>
<canvas id="diagonal" style="border: 1px solid;" width="200px" height="200px">Opps!</canvas>
<script>
function drawDiagonal(){
//取得Canvas元素及其绘图上下文
var canvas=document.getElementById('diagonal');
var context = canvas.getContext('2d');
//用绝对坐标创建一条路径
context.beginPath();
context.moveTo(70, 140);
context.lineTo(140, 70);
//正式绘制
context.stroke();
}
window.addEventListener("load", drawDiagonal, true);
</script>
</body>
</html>
9.2 矢量图形SVG初步
Canvas(画布)是基于像素(栅格)的图形、图像以及动画,而SVG(Scalable Vector Graphics,可缩放矢量图形)是基于矢量的。
<svg width="200" height="200">
<!--预定义,准备重复使用-->
<defs>
<g id="shapeGroup2">
<rect x="10" y="20" width="100" height="80" stroke="red" fill="#ccc" />
<circle cx="120" cy="80" r="40" stroke="#00f" fill="none" stroke-width="8" />
</g>
</defs>
<!--//重复使用-->
<use xlink:href="#shapeGroup2" transform="translate(60,0) scale(0.5)" />
<use xlink:href="#shapeGroup2" transform="translate(120,80) scale(0.4)" />
<use xlink:href="#shapeGroup2" transform="translate(20,60) scale(0.25)" />
</svg>
效果:
9.3 HTML5音频视频初步
Audio
在Web页面中播放音视频的典型方式为:Flash、QuickTime、Windows Media插件,而HTML5是直接提供的 原生支持,无需这些插件,同时提供了通用、集成以及可JavaScript控制的API。
<audio controls>
<source src="../assets/av/johann_sebastian_bach_air.mp3">
<source src="../assets/av/johann_sebastian_bach_air.ogg">
巴赫的舒缓音乐
</audio>
Video
<video controls autobuffer="true" width="100%" poster="../assets/img/poster.jpg">
<source src="../assets/av/oceans.mp4">
不支持的浏览器
</video>
9.4 地理定位及地图
HTML5提供了全新的Geolocation API,当请求一个位置信息时, 如果用户同意,则浏览器通过支持HTML5地理定位功能的底层设备(如手机的 GPS等)得到该信息。位置信息一般由纬度、经度及其它数据构成,我们则可以此 构建位置感知类应用程序如地图查看、导航、租房指南等。
定位的完整过程:
用户从浏览器打开位置感知应用页面
页面加载后将调用Geolocation函数请求位置
浏览器拦截该调用,向用户发出许可请求。如用户拒绝则什么都不会发生,否则
浏览器将从上述的底层(宿主)设备检索位置信息如IP、GPS等
浏览器将该位置信息发给它预设的、受信任的外部定位服务器,以期得到更详细的位置信息
浏览器将该详细位置信息返回给页面应用
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>HTML5地理位置定位</title>
<!--引入Google或Sougo地图库-->
<!--<script src="https://maps.google.com/maps/api/js?sensor=false"></script>-->
<script src="https://api.go2map.com/maps/js/api_v2.5.1.js"></script>
<script type="text/javascript">
function loadMap(){
if(navigator.geolocation){
document.getElementById("status").innerHTML = "获取数据中...";
navigator.geolocation.getCurrentPosition(onSuccess, onError, {timeout: 5000});
}else{
document.getElementById("status").innerHTML = "浏览器不支持!";
}
}
// 执行成功的回调方法
function onSuccess(position){
var latitude = position.coords.latitude;
var longitude = position.coords.longitude;
// 生成经纬度组合数据
// var latlon=new google.maps.LatLng(latitude,longitude);
var latlon = new sogou.maps.LatLng(latitude, longitude);
// 选择元素
var mapholder=document.getElementById('mapholder');
//选项:中心、放大、地图类型、控制按钮
var myOptions={
center:latlon,
zoom:14,
// mapTypeId:google.maps.MapTypeId.ROADMAP,
mapTypeId:sogou.maps.MapTypeId.ROADMAP,
mapTypeControl:true
};
// 以选项在页面指定位置生成地图
// var map=new google.maps.Map(mapholder,myOptions);
var map = new sogou.maps.Map(mapholder, myOptions);
document.getElementById("status").innerHTML = "Sogou地图";
// 生成标注
// var marker=new google.maps.Marker({position:latlon,map:map, title:"您在这儿"});
var marker = new sogou.maps.Marker({position:latlon, map:map, title:"您在这儿"});
//创建标注窗口
// var infowindow = new google.maps.InfoWindow({
// content:"您在这里<br/>纬度:"+ latitude + "<br/>经度:" + longitude
// });
var infoWindow = new sogou.maps.InfoWindow({
content:"您在这里<br/>纬度:"+ latitude + "<br/>经度:" + longitude
});
//显示标注窗口
infoWindow.open(map,marker);
}
// 失败时的回调方法
function onError(error){
var status = document.getElementById("status");
switch(error.code){
case error.PERMISSION_DENIED:
status.innerHTML = "用户不允许!"; break;
case error.POSITION_UNAVAILABLE:
status.innerHTML = "地理信息数据不可用!使用我家的固定坐标数据。";
display();
break;
case error.TIMEOUT:
status.innerHTML = "获取地理信息数据超时!使用我家的固定坐标数据。";
display();
break;
default :
status.innerHTML = "发生未知错误!"; break;
}
}
function display(){
var myLatlng = new sogou.maps.LatLng(29.502782699999997,106.57155259999999);
var myOptions = {
zoom: 14,
center: myLatlng,
mapTypeId: sogou.maps.MapTypeId.ROADMAP
};
map = new sogou.maps.Map(document.getElementById("mapholder"), myOptions);
marker = new sogou.maps.Marker({position:myLatlng, map:map, title:"我的家"});
}
</script>
</head>
<body onload="loadMap()">
<h1>HTML5位置定位示例</h1>
<p id="status"></p>
<div id="mapholder" style="width:900px;height: 500px"></div>
</body>
</html>