夯基础 - JavaScript之重头再来
1. 引入JavaScript
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 内部写-->
<!-- <script>-->
<!-- alert('hello');-->
<!-- </script>-->
<!-- 外部引入-->
<script src="js/1.js"></script>
<!-- 不写type默认-->
<script type="text/javascript">
</script>
</head>
<body>
</body>
</html>
2. 基本语法入门
<!-- JavaScript严格区分大小写-->
<script>
// 1. 定义变量 变量类型 变量名 = 变量值;
var num = 1;
alert(num);
// 2. 条件控制 可以嵌套使用
if(2 > 1){
alert('true');
console.log(num); // 控制台输出
}
</script>
浏览器调试工具
3. 数据类型
数值、文本、图形、音频、视频
number
js 不区分小数与整数,Number
123 // 整数123
123.1 // 浮点数123.1
1.123e3 // 科学计数法
-99 // 负数
NaN // not a number
Infinity // 表示无限大
字符串
‘abc’ “abc”
布尔值
true、false
逻辑运算
&& || !
⭐比较运算符
=
== 等于(类型不一样,值一样 也会判断为true)
=== 绝对等于(类型一样,值一样,结果为true)
这是js的缺陷,不要使用 == 比较
ps:NaN === NaN 为false,与所有值包括自己都不等,只能通过isNaN(NaN) 判断
浮点数问题
console.log((1/3) === (1 - 2/3)); // 为false
尽量避免使用浮点数进行运算,存在精度问题
null 和 undefined
空与未定义,不是一回事
数组
JS中不需要一系列相同类型的对象也可以称为数组
// 保证代码可读性 尽量使用[]
var arr = [1,2,3,'hello',null, true];
new Array(1,23,5,4,true);
取越界数组下标会undefined
对象
对象是大括号,数组是中括号,每个属性用逗号隔开,最后不用
var person = {
name: "快乐哥",
age: "18",
tags: ['js', 'vue', 'py']
}
//取对象的值
person.name
> "快乐哥"
person.age
> 18
3.1 严格检查模式
<!--
前提是支持ES6语法
'user strict'; 严格检查模式,预防js随意性导致产生的一些问题
必须写在js的第一行!
局部变量建议使用 let 定义
-->
<script>
'user strict';
// 全局变量
i = 1; // 这里严格检查模式便会报错
let i = 1; // 改为这个
</script>
3.2 字符串
-
正常字符串使用单引号或者双引号包裹
-
注意转义字符
\
\' \n \t \u4e2d // \u**** 为unicode字符 \x41 // Ascii字符
-
多行字符串编写 ES6新增
// tab 上面的 反单引号 `` var msg = ` hello world dongdongqiang `
-
模板字符串
// tab 上面的 反单引号 `` let name = 'zhang3'; let age = '18'; let msg = `hello ${name}`
-
一些方法、属性
msg.length; // 大小写转换的方法 msg.toUpperCase() msg.toLowerCase() //判断字符 msg.indexOf('x'); // 截取 student.substring(1); // 从第一个字符截取到最后一个 student.substring(1, 3);// 左闭右开 截取 [1, 3)
3.3 数组
Array可以包含任意的数据类型
var arr = [1,2,3,4,5,6];
> arr[0] = 1
-
长度
arr.length
注意:给arr.length赋值,数组大小会发生变化,对数组长度缩减会丢失数据
-
indexOf
获取元素下标索引 -
slice()
截取Array的一部分,返回一个新数组 -
push(); pop()
压入尾部与弹出尾部 -
unshift(); shift()
压入头部与弹出头部 -
arr.sort()
排序 -
arr.reverse();
数组反转 -
arr.concat([1,2,3]);
连接数组但是没修改原数组
3.4 对象
若干个键值对
var 对象名 = {
属性名 : 属性值,
属性名 : 属性值,
属性名 : 属性值
}
-
使用一个不存在的对象属性,不会报错! 返回
undefined
-
动态删减属性,通过delete删除对象的属性
delete person.name > true // 成功返回true
-
动态的添加,直接给新的属性添加值即可
person.gender = 'male' // 新添加gender属性
-
判断属性值是否在对象中
xxx in xxx
'age' in person > true // 存在返回true // 继承特性 'toString' in person > true
-
判断属性是否是对象自身(非继承)
hasOwnProperty();
person.hasOwnProperty('toString'); > false person.hasOwnProperty('gender'); > true
3.5 流程控制
if 条件判断
if(){
}else if(){
}else{
}
while循环
while(){
}
do.. while
do{
}while()
for 循环
for(){
}
forEach循环
var num = [1,2,3,4,5];
num.forEach(function(value){
console.log(value)
})
for...in
// for(var index in object){}
for(var i in age){
if(age.hasOwnProperty(i)){
console.log("exist")
console.log(age[i])
}
}
3.6 Map和Set
ES6新特性
Map
// 学生的成绩与姓名
var map = new Map([['tom', 100], ['jack', 98], ['luca', 89]]);
var name = map.get('tom'); // 通过key获得value
map.set('admin', 12345); // 新增或修改
map.delete('tom'); // 删除
Set 无序不重复的集合
set.add(2); // 添加
set.delete(1); // 删除
console.log(set.has(3)); // 是否包含某个元素
3.7 iterator
es6新特性
遍历数组
// 通过for of / for in 下标
var arr = [3, 4, 5]
for(var x of arr){
console.log(arr[x])
}
遍历map
var map = new Map([['tom', 100], ['jack', 98], ['luca', 89]]);
for(let x of map){
console.log(x);
}
遍历set
var set = new Set([1,2,3,4,5,6,6]);
for(let x of set){
console.log(x)
}
4. 函数及面向对象
4.1 函数定义及变量作用域
定义
定义方式一
// 定义一个绝对值函数
function abs(x){
if(x >= 0){
return x;
}else{
return -x;
}
}
一单执行到return代表函数结束,返回结果
如果没有执行return,函数执行完也会返回结果,结果为undefined
定义方式二
var abs = function(x){
if(x >= 0){
return x;
}else{
return -x;
}
}
这相当于一个匿名内部类function(x){}
但是可以吧结果赋值出去进行调用
js可以传任意个参数,甚至不需要参数
// 手动抛出参数异常
var abs = function(x){
if(typeof x !== 'number'){
throw 'not a number!';
}
if(x >= 0){
return x;
}else{
return -x;
}
}
arguments 为js中特有的关键字,代表传递进来的所有参数,为数组
var abs = function(x){
console.log("x -> "+ x);
for(var i = 0; i < arguments.length; i ++){
console.log(arguments[i]);
}
if(x >= 0){
return x;
}else{
return -x;
}
}
...reset
ES6 新特性,用以获取已经定义之外的所有参数
function abc(a,b, ...reset){
console.log("a -> "+ a);
console.log("b -> "+ b);
console.log("others -> "+ reset); // 后面多余的以数组形式获取
}
作用域
在js中 ,var定义变量实际是有作用域的
在函数之外调用里面定义的量为闭包知识,后头说
而在不同函数中定义相同的变量名不会冲突的
内部函数可以访问外部函数的成员,反之不行
function fun(){
var x = 1;
// 内部函数可以访问外部函数的成员
function fun2(){
var y = x + 1;
}
var z = y + 1; // Uncaught ReferenceError: y is not defined
}
假设,内部函数变量和外部函数变量重名
function fun(){
var x = 1;
function fun2(){
var x = 'A';
console.log('inner' + x); // innerA
}
console.log('outer' + x); // outer1
fun2();
}
假设js函数查找变量从自身开始,又内向外查找,假设外部存在变量,则内部会屏蔽外部的函数变量。
提升变量的作用域
function fun(){
var x = "x" + y;
console.log(x);
var y = 'y';
}
// 输出结果为 undefined
// 说明js执行引擎自动提升了y的声明,但是不会提升y的赋值,所以没有报错而是undefined
全局函数,定义在函数外的,相当于绑定到全局变量
window
上
var x = 'xxx';
alert(x);
alert(window.x); // 默认所有的全局变量,自动绑定在window下
alert(); 其本身也是一个window变量
var x = "xxx";
window.alert(x);
var old_alert = window.alert;
// 此时 old_alert(x) 是可以输出的
window.alert = function(){
};
// 此时alert() 失效
规范
建议为了减少冲突而把自定义的变量上升为全局变量
// 唯一全局变量
var myVar = {};
// 定义全局变量
myVar.name = 'z3';
myVar.add = function(a, b){ // 定义一个自己变量的加函数
return a + b;
};
把自己的代码放入自己的空间中
es6新增特性:局部作用域let
function fun(){
for(let i = 0; i < 100; i ++){
console.log(i) // 可以执行
}
console.log(i) // 不可以执行 因为 i 为 let定义的局部变量
}
const 常量
在es6之前,常量的定义仅为所有大写字母命名而成的变量,但是可以修改
const PI = '3.14'; // 这个新特性定义的const常量不可以被修改
PI = '123';
console.log(PI); // 此时报错 TypeError: Assignment to constant variable.
4.2 方法
定义方法
方法就是把函数放在对象里面,对象只有属性和方法
var myFun = {
name: 'z3',
birth: 2000,
// 方法
getAge: function(){
// 当前 - 出生
var age = new Date().getFullYear();
// 注意this的指向
return now - this.birth;
}
}
// 属性
myFun.name
// 执行方法一定要带()
myFun.getAge()
拆开写函数
function outAge(){
// 当前 - 出生
var age = new Date().getFullYear();
// 注意this的指向
return now - this.birth;
}
var myFun = {
name: 'z3',
birth: 2000,
// 方法
age: outAge
}
// myFun.age(); 可以执行
// outAge(); 返回NaN 因为this指向window 自然没有对象
apply
function outAge(){
// 当前 - 出生
var age = new Date().getFullYear();
// 注意this的指向
return now - this.birth;
}
var myFun = {
name: 'z3',
birth: 2000,
// 方法
age: outAge
}
// outAge.apply(l4, []); // this指向 l4, 参数为空
4.3 ⭐闭包
4.4 箭头函数(新特性)
4.5 创建对象
var stu = {
name:'z3',
age : 18,
gender: 'male',
run : function(){
console.log(this.name + 'is running');
}
}
var xiaom = {
name: 'xiaoming'
}
// proto 相当于一个父类,这里类似复制更改
xiaom.__proto__ = stu;
// 之后小明没有stu的方法时可以调用stu的run方法
// 以前定义一个类
fucntion Stu(name){
this.name = name;
}
// 给stu新增一个方法
Stu.prototype.hello = function(){
alert('hello');
};
4.6 class 继承(ES6新特性)
- 定义一个类、属性、方法
// 定义一个学生类
class Stu{
constructor(name){
this.name = name;
}
hello(){
alert("hello")
}
}
var xiaoming = new Stu("xiaoming");
var xiaohong = new Stu("xiaohong");
-
继承
// 定义一个学生类 class Stu{ constructor(name){ this.name = name; } hello(){ alert("hello") } } class junior extends Stu{ constructor(name, grade){ super(name); this.grade = grade; } myGrade(){ alert("i am a junior Stu") } } var xiaoming = new Stu("xiaoming"); var xiaohong = new junior("xiaohong", 1);
⭐原型链继承
5. 常用对象
5.1 Date
var now = new Date(); // 当前标准时间
now.getFullYear(); // 年
now.getMouth(); // 月
now.getDate(); // 日
now.getDay(); // 星期几
now.getHours(); // 时
now.getMinutes(); // 分
now.getSeconds(); // 秒
now.getTime(); // 时间戳 全球统一从1970 1.1 0:00:00 开始毫秒数
console.log(new Date(x)); // 将时间戳x转为标准时间
// 转换
now.toLocaleString // 调用的是一个方式,而不是属性
// 上一行报错 f toLocaleString(){ [native code] }
now.toLocaleString()
now.toGMTString()
5.2 JSON
json 是什么?
- JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
- 它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。
- 简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在js中一切皆为对象,任何js支持的类型都可以用json来表示;number、string...
格式为:
- 对象:{}
- 数组:[]
- 键值对:key:value
JSON字符串和JS对象的转化
var user = {
name:'z3',
age : 18,
gender: 'male'
}
// 对象转化为json字符串 {"name":"z3","age":18,"gender":"male"}
var jsonUser = JSON.stringify(user);
//json 字符串转为对象 参数为json字符串
var obj = JSON.parse('{"name":"z3","age":18,"gender":"male"}'); //键值对
// json 和 js对象的区别
// json
var jsonUser = '{"name":"z3","age":18,"gender":"male"}';
var obj = {a: 'hello', b:'world'};
5.3 Ajax
- 原生js写法 xhr异步请求
- jQuery封装好的方法
$(“#name”).ajax(“”)
- axios 请求
6. 操作Dom元素
整个网页就是一个Dom树形结构,进行增删改查的操作
6.1 获得Dom节点
// 对应css选择器
var h1 = document.getElementByTagName('x');
var p1 = document.getElementById('x');
var p2 = document.getElementByClassName('x');
var fat = document.getElementByTagName('father');
var chi = fat.children; // 获取父节点下的所有子节点
// fat.firstChild // 第一个子节点
// fat.lastChild // 最后一个子节点
6.2 创建、插入DOM
<body>
<p id="js">js</p>
<div id="list">
<p id="se">se</p>
<p id="ee">ee</p>
<p id="me">me</p>
</div>
</body>
<script>
var js = document.getElementById('js');
var list = document.getElementById('list');
list.appendChild(js); // 追加到后面
</script>
创建一个新的标签
<script>
var newP = document.creatElement('p'); // 创建一个标签P
newP.id = 'newP';
newP.innerText = 'HelloWorld!';
// 创建一个标签节点
var myScript = document.creatElement('script');
myScript.setAttribute('type', 'text/javascript');
</script>
6.3 更新DOM
<div id = 'a'> </div>
<script>
var ia = document.getElementById('a');
</script>
-
ia.innerTetx = ‘aaaa’
修改文本值 -
ia.innerHTML = ‘<strong>bbb</strong>’
支持网页标签 -
//操作css ia.style.color = 'red'; // 属性使用字符串包裹 ia.sytle.fontSize= '20px'; // 驼峰命名 ia.style.padding = '2em'
6.4 删除DOM
先获取父节点,再通过父节点删除自己
<div id = 'father'>
<h1> title </h1>
<p id = 'p1'>p1</p>
<p id = 'p2'>p2</p>
</div>
<script>
var selt = document.getElementById('p1');
var father = p1.parentElement;
father.removeChild(self)
//按照索引删除注意动态改变下标
father.removeChild(father.children[0]);
</script>
7. 操作Bom元素
Bom浏览器对象模型
7.1 window
window.alert();
window.innerHeight; // 内部高度
window.innerWidth; // 内部宽度
window.outerHeight; // 外部高度
window.outerWidth; // 外部高度
...
7.2 navigator
大多数时候不会使用navigator ,因为可以人为修改,不建议使用
navigator.appName
"Netscape"
navigator.appVersion
"5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4350.7 Safari/537.36"
navigator.userAgent
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4350.7 Safari/537.36"
navigator.platform
"Win32"
7.3 screen
screen.width
1920
screen.height
1080
// 尺寸信息
7.4 ⭐location
hash: ""
host: "new-tab-page" // 主机
hostname: "new-tab-page"
href: "chrome://new-tab-page/"
origin: "chrome://new-tab-page"
pathname: "/"
port: ""
protocol: "chrome:" // 协议
reload: ƒ reload() // 重新加载 刷新网页
replace: ƒ replace()
search: ""
toString: ƒ toString()
valueOf: ƒ valueOf()
Symbol(Symbol.toPrimitive): undefined
__proto__: Location
// 重定向
location.assign('www.xxxx.com');
7.5 Document
HTML DOM 文档树
document.title
document.title = 'xxxxx'
document.getElementById('...')
document.cookie // 获取cookie
7.6 History
history.back(); // 后退
history.forward(); // 前进
7.7 操作表单
获得提交的信息
<form action = "post">
<p>
<span>UserName:</span><input type = "text" id = "username">
</p>
<!-- 多选框的值是定义好的value -->
<p>
<span>Gender</span>
<input type = "radio" name = "gender" value = "male" id = "boy" > 男性<input type = "radio" name = "gender" value = "female" id = "girl" > 女性
</p>
</form>
<script>
var input_text = document.getElementById('username');
var boy_radio = document.getElementById('boy');
var girl_radio = document.getElementById('girl');
// 得到输入框的值
input_text.value
// 膝盖输入框的值
input_text.value = 'xxx'
// 对于单选框等固定的值, boy_radio.value 只能取得当前的值
boy_radio.checked; // 查看返回的结果是否为true,选中则为true
</script>
提交表单的两种方法
<!-- HTML -->
<form id="test-form">
<input type="text" name="test">
<button type="button" onclick="doSubmitForm()">Submit</button>
</form>
<script>
function doSubmitForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 提交form:
form.submit();
}
</script>
<!-- HTML -->
<form id="test-form" onsubmit="return checkForm()">
<input type="text" name="test">
<button type="submit">Submit</button>
</form>
<script>
function checkForm() {
var form = document.getElementById('test-form');
// 可以在此修改form的input...
// 继续下一步:
return true;
}
</script>
md5 密码加密
- 解决问题:用户输入了口令提交时,口令框的显示会突然从几个
*
变成32个*
(因为MD5有32个字符) - 注意:
id
为md5-password
的<input>
标记了name="password"
,而用户输入的id
为input-password
的<input>
没有name
属性。没有name
属性的<input>
的数据不会被提交。
<!-- HTML -->
<form id="login-form" method="post" onsubmit="return checkForm()">
<input type="text" id="username" name="username">
<input type="password" id="input-password">
<input type="hidden" id="md5-password" name="password">
<button type="submit">Submit</button>
</form>
<script>
function checkForm() {
var input_pwd = document.getElementById('input-password');
var md5_pwd = document.getElementById('md5-password');
// 把用户输入的明文变为MD5:
md5_pwd.value = toMD5(input_pwd.value);
// 继续下一步:
return true;
}
</script>
7.8 操作文件
8. jQuery
把jQuery比作一个类库
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script src="../jquery-3.5.1.min.js"></script>
</head>
<body>
<a href="" id = "clickHere">Click here!</a>
<script>
// 利用jQuery公式 $(selector).action()
$(clickHere).click(function(){
alert('hello world!');
})
</script>
</body>
</html>