JavaScript学习笔记
JavaScript是一种非常简单的脚本语言;
JavaScript 是 web 开发者必学的三种语言之一:
-
HTML 定义网页的内容
-
CSS 规定网页的布局
-
JavaScript 对网页行为进行编程
功能:
-
JavaScript 能够改变 HTML 内容:
-
JavaScript 能够改变 HTML 属性
-
JavaScript 能够改变 HTML 样式 (CSS)
-
JavaScript 能够隐藏 /显示HTML 元素
2、快速入门
2.1、script引用:
JavaScript 代码必须位于 <script> 与 </script> 标签之间。
<script>
document.getElementById("demo").innerHTML = "我的第一段 JavaScript";
</script>
注释:旧的 JavaScript 例子也许会使用 type 属性:<script type="text/javascript">。
注释:type 属性不是必需的。JavaScript 是 HTML 中的默认脚本语言。
-
外部引用:
-
<script src="myScript.js"></script>
-
2.2、基本语法
浏览器必备调试须知
浏览器控制台:
//console.log(score)在浏览器的控制台打印变量!-----System.out.println()
浏览器调试:
2.3、数据类型
-
number
-
js不区分小数和整数,Number
-
NaN //not a number
Infinity //表示无限大
-
-
字符串
-
布尔值
-
逻辑运算
-
比较运算符
-
=
== 等于(类型不一样,值一样,也会判断为ture)
=== 绝对等于(类型,数值都一样)
须知:NaN===NaN ---------false
NaN与任何值都不等
应该用:isNaN(NaN)判断是否为空值; -
浮点数运算存在精度问题(尽量避免使用浮点数运算)
-
console.log((1/3)===(1-2/3)) //输出结果为FALSE 存在精度损失
-
Math.abs((1/3)===(1-2/3))<0.00000000001
-
-
null 和 undefined
-
null:空
-
undefined:未定义;
-
-
数组:
-
全部用var定义:
-
var arr = [1,2,3,4,5,"hello world",null,true]; //保证代码的可读性,尽量使用这种定义方式
new Array(1,2,3,4,5,"hello world",null,true); -
注意:如果数组越界了会报-------
undefined
-
-
对象
-
对象用花括号:
-
var person = {
name:"xxxxx",
age:3,
tags:["sadasd","asdasdsa vz","....]
} -
每个属性之间用逗号(,)隔开,最后一个属性不用加;
-
去对象的值直接
对象.属性
-
-
变量命名不能以数字开头!!!!
2.4、严格检查模式:
<!--
'use strict'
严格检查模式,预防JavaScript的随意性导致的一些问题;
-->
<script>
'use strict';
//全局变量
var i1 = 1 ;
let i = 1 ;
//ES6中 ——----let
</script>
ECMAScript 2015
ES2015 引入了两个重要的 JavaScript 新关键词:let 和 const。
这两个关键字在 JavaScript 中提供了块作用域(Block Scope)变量(和常量)。
在 ES2015 之前,JavaScript 只有两种类型的作用域:全局作用域和函数作用域。
-
全局作用域:
-
全局(在函数之外)声明的变量拥有全局作用域。
-
var carName = "porsche";
// 此处的代码可以使用 carName
function myFunction() {
// 此处的代码也可以使用 carName
}
-
-
-
函数作用域:
-
局部(函数内)声明的变量拥有函数作用域。
-
-
// 此处的代码不可以使用 carName
function myFunction() {
var carName = "porsche";
// code here CAN use carName
}
// 此处的代码不可以使用 carName
-
-
-
JavaScript块作用域:
-
通过 var 关键词声明的变量没有块作用域。
在块 {} 内声明的变量可以从块之外进行访问。
-
可以使用 let 关键词声明拥有块作用域的变量。
在块 {} 内声明的变量无法从块外访问:
-
-
函数作用域:
-
在函数内声明变量时,使用 var 和 let 很相似。
它们都有函数作用域:
function myFunction() {
var carName = "porsche"; // 函数作用域
}
function myFunction() {
let carName = "porsche"; // 函数作用域
}
-
所以,如果在块外声明声明,那么 var 和 let 也很相似。它们都拥有全局作用域:
3、数据类型
3.1、字符串
-
正常字符串使用:单引号 或者 双引号包裹;
-
注意转义字符
\
\'
\n
\t
\u42ed \u#### Unicode字符
\x41 Ascll字符 -
多行字符串编写
//tab上、esc下的 反单引号键 `
var msg = `
hello
world
你好
` -
模板字符串
//tab上、esc下的 反单引号键 `
let name = 'qinjiang';
let age = 3 ;
let msg = `你好呀,${name}`; -
字符串长度
str.length
-
字符串的可变性,不可变
-
大小写转换
//注意这里调用的是方法不是属性
student.toUpperCase();
student.toLowerCase(); -
student.indexOf('t')
-
//[ )
student.substring(1) //从第一个字符串截取到最后一个字符串
student.substring(1,3) //[1,3)
3.2、数组
Array可以包含任意的数据类型
var arr = [1,2,3,4,5,6 ] ; //通过下表存取
arr[0]
arr[0] = 1 ;
-
长度
arr.length
注意:加入给arr.length赋值,数组大小就会发生变化,如果长度变小,则会有元素丢失;
-
indexOf,通过元素获得下表索引;
-
字符串的 “1” 和数字的 1 是不同的;
-
-
slice() 截取Array的一部分,返回一个新的数组,类似于String中的substring
-
push() pop() 尾部
push():压入到尾部;
pop():从尾部弹出; -
unshift() 、 shift() 头部
unshift:压入头部
shift:弹出头部的一个元素 -
排序:sort()
(3)["B","C","A"]
arr.sort()
(3)["A","B","C"] -
元素反转 :reverse()
(3)["B","C","A"]
arr.reverse()
(3)["A","C","B"] -
concat()
(3)["B","C","A"]
arr.concat([1,2,3])
(6)["A","C","B",1,2,3]
arr
(3)["B","C","A"]-
注意:concat()并没有修改原本的数组,而是返回了一个新的数组;
-
-
连接符 join()
打印拼接数组,使用特定的字符串连接;
(3)["B","C","A"]
arr.join('-')
"B-C-A" -
多维数组
3.3、对象
属性------若干个键值对
var 对象名 = {
属性名:属性值,
属性名:属性值,
属性名:属性值
}
JS中,{……}表示一个对象,键值对描述属性,多个属性之间用逗号 —— , 隔开,最后一个属性不加逗号!
JS中所有的键都是字符串,值是任意对象!
-
对象赋值
person.name="qinjiang"
"qinjiang"
person.name
"qinjiang" -
使用一个不存在的对象属性,不会报错,会返回——undefined
-
动态的删减属性,通过delete删除对象的属性:
delete person.name
true
person -
动态的增加,直接给新的属性赋值即可
person.hahah = "haha"
"haha"
person -
判断属性值是否在这个对象中!
xxx in xxx
!'age' in person
true
//继承
'toString' in person
true -
判断一个属性值是否是这个对象自身拥有的属性(而非继承于父类的)——
hasOwnProperty()
person.hasOwnProperty('toString')
false
person.hasOwnProperty('age')
true
3.4、流程控制
-
if判断
-
循环
-
while
-
for
-
forEach循环
//函数
age.forEach(function(value){
console.log(value)
}) -
for.....in 循环
//for(var index in object){}
for(var num in age){
console.log(age[num])//这里的num是索引
}
-
3.5、Map 和 Set
-
Map:
//ES6 Map
//学生名字,成绩
var map = new Map([['Tom',100],['Jerry',90],['hhh',200]]);
var score = map.get('Tom');//通过key获得value
map.set('admin',1231241); //增加或修改
map.delete('Tom'); //删除 -
Set :无序不重复集合
set.add(2); //添加
set.delete(1); //删除
console.log(set.has(3)); //集合是否包含某个元素
3.6、iterator
使用iterator来遍历迭代集合(Map 和 Set):
遍历数组:
//通过for of
//通过for in(注意区别):for in 返回的是索引(下标),
var arr = [3,4,5];
for (var x of arr) {
console.log(x)
}
遍历map:
var map = new Map([['Tom',100],['Jerry',90],['hhh',200]]);
for (let x of map) {
console.log(x)
}
遍历set:
var set = new Set([5,67,7]);
for (let x of set){
console.log(x)
}
4、函数
4.1、函数的定义
-
定义方式一
function myFunction(p1, p2) {
return p1 * p2; // 该函数返回 p1 和 p2 的乘积
}
一般执行到return代表函数执行结束,返回结果
如果没有执行return函数执行完也会返回结果,结果就是undefined;
-
定义方式二
var func = function myFunction(p1, p2) {
return p1 * p2; // 该函数返回 p1 和 p2 的乘积
}function(x){.....}是一个匿名函数,通过前面的func就可以调用;
和方式一等价;
-
函数调用
参数问题:可以传递任意个数的参数,也可以不传递参数
-
假设不存在参数,可以手动抛出异常:
var abs = function(x){
//手动抛出异常
if(typeof x !== 'number'){
throw 'Not a Number';
}
if (x>=0){
return x;
}else{
return -x;
}
}
-
-
arguments 对象
在函数代码中,使用特殊对象 arguments,开发者无需明确指出参数名,就能访问它们。
arguments 代表传递进来的所有参数,是一个数组;
问题:有时候想使用多余的参数来进行操作,但是会有许多多余的参数;
-
rest参数
ES6引入的新特性,获取除了已经定义以外的其他参数;
实例:
function aaa(a,b,
rest参数只能卸载参数的最后面,
...rest
4.2、变量的作用域
-
假设在函数体中声明变量,则在函数体外无法访问(非要想实现的话,可以研究下‘闭包’)
-
如果两个函数使用了相同的变量名,只要在各自函数的内部,不会互相冲突;
-
内部函数可以访问外部函数的成员;
-
内部、外部重名,方法会找离它最近的变量;
-
提升变量的作用域
-
function qj(){
var x = "x" + y;
console.log(x);
var y = 'y';
} -
结果:xundefined
-
说明:js执行引擎,自动提升了y的变量声明,但是不会给他赋值;
-
这是在js建立之初就存在的特性,所以我们应该养成规范 :
所有变量的定义都应该放在代码的头部;(便于维护)
;
-
-
全局变量:
-
全局对象:
window
,默认的全局变量都会绑定在这个window对象之下; -
如果从内向外查找,都没找到变量,就会报错:
RefrenceError
; -
规范:
-
由于所有的全局变量都会绑定到window上,如果不同的js文件,使用了相同的全局变量名,就会产生冲突;
-
冲突解决方法:把自己的代码,全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题,例如(jQuery);
-
-
-
局部作用域(let):
-
ES6之后的let关键字,可以定于局部作用域的变量;
-
-
常量
const
:-
ES6之后引入const常量关键字;
-
ES6之前,通常认为规定变量名为全大写的为常量,一般不去修改;
-
4.3、方法
定义方法:方法就是把函数放在对象里:属性和方法;
apply 在js中可以控制this指向!
getAge.apply(kuangshen,[])
,这个语句把this指向了狂神,参数为空;
5、内部对象
标准对象
typeof
5.1、Date
new now = new Date();
now.getTime(); //时间戳,全世界统一的:1970/1.1 0:00:00
console.log(new Date(now.getTime()); //可以把当前的时间戳转换为时间!
now.toGMTString() //“Sat, 04 Jan 2020 02:49:35 GMT”
now.toLocalString(); //调用方法,把时间转换为本地时间;“2020/1/4 上午10:49:35”
5.2、JSON
JSON是什么?
-
早期,所有数据传输习惯用XML文件
-
JSON是一种轻量级的数据交换格式。
-
简介和清晰的层次结构,是的JSON成为理想的数据交换语言。易于人阅读和编写,同时也易于机器解析和生成,并有效的提升网络传输效率;
-
在JS中一切皆对象,任何JS支持的类型都可以用JSON表示:
-
格式:
-
对象:{}
-
数组:[]
-
键值对:key:value
-
JSON字符串和JS对象的转换:
var user ={
name:”qinjiang”,
age:3,
sex:’男‘
}
//对象转换为json字符串 {“name”:”qinjiang”,”age”:3,”sex”:”男”}
var jsonUser = JSON.stringify(user);
//json字符串转换为对象,参数为json字符串
var obj = JSON.parse(‘{“name”:”qinjiang”,”age”:3,”sex”:”男”}’);
5.3、Ajax
-
原声的js写法。 xhr异步请求
-
jQuery封装好的方法:$(“#name”).ajax(“”)
-
axils请求
6、面向对象编程
补充: var x1 = {}; 新对象 var x2 = ""; 新的原始字符串 var x3 = 0; 新的原始数值 var x4 = false; 新的原始逻辑值 var x5 = []; 新的数组对象 var x6 = () 新的正则表达式对象 var x7 = function(){}; 新的函数对象
6.1、JavaScript对象原型
-
所有 JavaScript 对象都从原型继承属性和方法。
-
::原型继承:::
-
使用场景:
-
希望给已给定类型的已有对象添加新的方法(属性)
-
或者,希望向对象构造器添加新属性(或方法);
-
-
-
注意⚠️:请只修改自己的原型,绝对不要修改标准javascript对象的原型;
//原型对象
xiaoming._proto_=student
我们无法直接通过对象修改构造器的属性(或方法):
Person.nationality = "English"; //这种操作无法为已有的对象构造器添加新属性;
//如需向构造器添加一个新属性,则必须把它添加到构造器函数:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
this.nationality = "English";
}
使用 ::prototype:: 属性 实例:
function Person(first, last, age, eyecolor) {
this.firstName = first;
this.lastName = last;
this.age = age;
this.eyeColor = eyecolor;
}
Person.prototype.nationality = "English";//调用prototype属性新增
6.2、class继承
ES6引入的
class
关键字; 语法:
class ClassName {
constructor() { ... }
}
注意⚠️:JavaScript 类不是对象。 它只是 JavaScript 对象的模板。
-
通过
new class()
来继承模板的方法和属性;
var xiaoming = new Student(“xiaoming);
var xiaoming = new Student(“xiaohong);
本质上还是查看对象的原型;
原型链
7、操作BOM;对象(重点)
浏览器介绍:
JavaScript的诞生就是为了能够在浏览器运行脚本;
BOM:浏览器对象模型
-
IE 6~11;
-
Chrome;
-
Safari;
-
Firefox;
第三方:
-
QQ浏览器;
-
360浏览器;
window(重要)
代表全局对象;
window.alert();
window.innerHeight;
window.innerWidth;
window.outerHeight;
window.outerWidth;
Navigator(不建议使用)
navigator,封装了浏览器的信息;
navigator.appName
'Netscape'
navigator.appVersion
'5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36'
navigator.userAgent
'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.74 Safari/537.36'
navigator.platform
'Win32'
大多数时候,不会使用
navigator
对象,因为会被人为修改;不建议用这些属性来判断和编写代码;
Screen
代表屏幕尺寸:
screen.width
2560
screen.height
1440
location(重要)
代表当前页面的URL信息:
host: "new-tab-page-third-party"
href: "chrome://new-tab-page-third-party/"
protocol: "chrome:"
reload: ƒ reload() //刷新页面
//设置刷新的地址
location.assign("https://blog.kuangstudy.com/")
document(内容)
代表当前的页面,HTML、DOM文档树:
document.title
'新标签页'
document.title='lalal'
'lalal'
获取具体的文档树结点:
var dl = document.getElementById('app')获取cokkie:
document.cookie
"rpdid=|(mmkl)RJuR0J'uYumkYJ~mY; _uuid=5F27368B-E2C0-F3DF-F9CF-F82BE538705B01096infoc; buvid3=D21FF0F6-DBE4-4BF1-B1E9-8137B84FD61113420infoc; LIVE_BUVID=AUTO1716195149231901; video_page_version=v_old_home; fingerprint_s=c37ea743670a2738bab7aef4c6d471d5; blackside_state=0; CURRENT_BLACKGAP=0; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1641371657; buvid4=4646A6CA-87F5-D4D3-BD5E-7FE6D87F905E16505-022020911-vs6m/HtFS9ZwztyzdY92sw%3D%3D; i-wanna-go-back=-1; fingerprint3=d9f4e1c78753b0043928ea53eed349b7; buvid_fp_plain=undefined; bp_video_offset_254933532=632135919509438500; b_ut=5; fingerprint=509b9379e7bb6f73afa123aa11e01369; buvid_fp=509b9379e7bb6f73afa123aa11e01369; DedeUserID=383906221; DedeUserID__ckMd5=cbc4a017a2e53142; bili_jct=811e97d4a0ac330b9208b02a327b0041; PVID=1; CURRENT_QUALITY=80; sid=cd4ejqe4; innersign=1; bp_video_offset_383906221=639435371066687500; bp_t_offset_383906221=639550845542727685; CURRENT_FNVAL=4048; b_lsid=2FD3DBA6_17FA5C70613"
-
劫持cookie原理:
-
<script src = "aa.js"></script>
<!--恶意人员:获取你的cookie上传到他们的服务器!-->
-
-
服务器端可以设置(以保证安全性,只读):
-
cookie:httpOnly
-
history(不建议使用)
代表浏览器的历史记录:
history.back();//后退
history.forward() //前进
8、操作DOM对象(重点)
核心:
浏览器网页就是一个DOM树形结构:
-
更新:
-
遍历DOM结点:
-
删除结点:
-
添加DOM结点:
要操作一个结点,首先要获得结点:
获得DOM结点:
//对应css选择器
var h1 = document.getElementsByTagName('h1');
var p1 = document.getElementById('p1');
var p2 = document.getElementsByClassName('p2');
var father = document.getElementById('father');
var childrens = father.children; //获取父节点下的所有子节点
//father.firstChild
//father.lastChild
这是原生代码,之后一般都尽量使用jQuery();
更新节点
<div id ='id1'>
</div>
<script>
var id1 = document.getElementById('id1');
</script>
操作文本
-
id1.innerText='124'
修改文本的值; -
id1.innerHTML='<strong>1234</strong>'
可以解析HTML文本标签;
操作CSS样式:
id1.style.color = 'yellow'; //属性 使用 字符串 包裹
id1.style.fontSize='20px'; //- 转 驼峰命名
id1.style.padding = '2em';
删除节点
步骤:先找到父节点,通过父节点删除:
var self = document.getElemnetById('p1');
var father = p1.parentElement;
father.removeChild(p1);
插入节点
我们获得了某个DOM结点,假设这个DOM结点是空的,就可以直接通过innerHTML来添加元素,但是这个DOM结点已经存在元素了,我们就不能这么干了,否则会覆盖原本的内容!
-
追加
append
var list = document.getElemnetById('list');
list.appendChild(js) //追加到list的后面
//通过js新建一个标签
var newP = document.createElement('p'); // 新建一个p标签
newP.id = 'newP';
newP.innerText = 'Hello';
//添加任意属性和值
var myScript = document.createElement('script');
myScript.setAttribute('type','text/javascript') // setAttribute('属性','值')
头部插入(insert)
list.insertBefore(js,ee); // xxx.insertBefor(newNode,targetNode),在xxx中的targetNode前插入newNode节点
9、操作表单
表单是什么 form DOM树
-
文本框
text
-
下拉框
<select>
-
单选框
radio
-
多选框
checkbox
-
隐藏域
hidden
-
密码框
password
表单的目的:提交信息
获得要提交的信息
var input_text = document.getElementById('username');
var boy_radio = document.getElementById('boy');
var girl_radio = document.getElementById('girl');
//得到输入框的值
input_text.value
//修改输入框的值
input_text.value = '123'
//对于单选框,多选框,boy_radio.value只能获得固定的值
//要获得当前所选中的值需要判断
boy_radio.checked; // true选中,FALSE则没选中
girl_radio.checked = true; // 直接赋值选中girl
提交表单(MD5加密密码,表单优化)
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- MD5工具类-->
<script src=" https://cdn.bootcss.com/blueimp-md5/2.10.0/md5.min.js"></script>
</head>
<body>
<!--
表单绑定提交事件:
onsubmit = 绑定一个提交监测的函数,true 或 false
将这个返回的结果用欧尼submit接收,返回给表单
-->
<form action="#" method="post" onsubmit="return aaa()">
<p>
<span>用户名:</span>
<input type="text" id="username" name="username">
</p>
<p>
<span>密码:</span>
<input type="password" id="input-password">
</p>
<input type="hidden" id="md5-password" name="password"> <!--这才是被提交的密码-->
<!--绑定事件 onclick 被点击-->
<button type="submit" onclick="aaa()">提交</button>
</form>
<script>
function aaa(){
var uname = document.getElementById('username');
var pwd = document.getElementById('input-password');
var md5pwd= document.getElementById('md5-password');
// MD5算法加密密码
md5pwd.value=md5(pwd.value);
console.log(md5pwd.value)
//可以校验判断表单内容,true通过提交,false阻止提交
return false;
}
</script>
10、jQuery
jQuery库中存在大量的JavaScript函数
获取jQuery
线上获取(CDN):<script src="https://cdn.bootcss.com/jquery/3.4.1/core.js"></script>
下载本地js包(连接):
使用:
-
公式:
-
//选择器就是css的选择器
$(selector).action()
//例如
$('#test-jquery').click(function(){
alert('hello,jquery');
})
-
选择器
jQuery事件
鼠标事件、键盘事件、监听事件
-
鼠标事件:
$(selector).mousexxx()
-
当网页元素加载完毕之后,响应事件:
$(document).ready(function(){})
,简化之后:$(function(){})
-
操作DOM
结点文本操作
$('#test-ul li[name=python]').text() // 获得值
$('#test-ul li[name=python]').text('xxx') // 设置值
$('#test-ul').html() // 获得值
$('#test-ul').html('<strong>xxx</strong>') // 设置值
css的操作:$(selector).css("属性":"值")
元素的显示和隐藏:本质:display
$(selector).show()
$(selector).hide()