JavaScript学习笔记
一、样例
- 引入方法:内部标签,外部引入
- 代码如下:
- HTML
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!-- 内部标签,script标签内,写Javascript代码 -->
<script>
alert('hello world');//弹窗
</script>
<!--外部引入-->
<script src="js/js1.js"></script>
<!-- 不用显示定义type,也默认就是javascript -->
<script type="text/javascript">
//所以注释可以//这样写
</script>
</head>
<body>
<!--这里也可以存放js代码-->
</body>
</html>
- js1.js
alert("引入的标签")
二、基本语法
- 定义变量
var+变量名(=...)
- 每一句加;和Java语法一样
- ifelse语句
- 注意,JavaScript也严格区分大小写
- 可以在页面->审查元素->console直接编辑代码
-
//console.log(score)在浏览器的控制台打印变量,等价于System.out.println();
- 页面编辑器设置断点并调试:点击行号并刷新即可调试
- 浏览器常用的几个功能模块
三、数据类型
- javascript不区分小数和整数
- 字符串
- 布尔值
- &&,||,!
- 极其重要!!!不能用==判断相等!
须知:
- NaN===NaN
不能判断,NaN不等于任何数!包括自己!
- 只能通过isNaN(NaN) 来判断这个数是否是NaN
-
浮点数存在精度的损失
-
粗略判断浮点数相等的方法:
Math.abs(1/3-(1-(2/3))<0.000000001
-
null和undefined
-
数组
var nums=[1,2,"3",null,true]
- 打印数组
console.log(var[0])
- 打印数组
-
对象
- 对象是大括号,数组是中括号
- 每个属性之间用逗号隔开,最后一个不用
var person={
name:"111",
age:1
}
四、严格检查类型strict
'use strict'
严格检查模式,预防JavaScript的随意性导致一些问题,必须写在JavaScript第一行- 局部变量建议使用 let 定义
<script>
'use strict';//加入这条语句,全局变量就会报错
//全局变量
i=1
//局部变量
let j=1
</script>
五、字符串类型
- 转义
'\'
``
Tab与Esc之间:- 多行字符串
- 模板字符串
<script>
'use strict';
let num=1;
console.log(num);
console.log('a\'a\'b');
let nums=`模板字符串
换行 模板字符串
`;
let msg=`hello,${nums}`;
console.log(msg);
</script>
-
字符串长度
str.length
-
取字符串某一元素:
str[0]
-
字符串的可变性:不可变
-
这里插句话,一开始我在控制台输入var num=1后反复报错,一直以为是文件本身格式有问题,上网搜半天,最后查看代码才发现原来是反复定义的问题
-
大小写转换
str.toUpperCase(),str.toLowerCase()
let str="abc"
console.log(str.toUpperCase());
console.log(str.toLowerCase());
- 字符串取字符下标
str.indexOf()
let str="abccc"
console.log(str.indexOf("c"));//2
- 删去部分字符串
srb.substring()
let str="abccc"
console.log(str);
console.log(str,str.substring(1,2));//前闭后开
console.log(str,str.substring(1));//按0算,第1个往后
六、数组类型
-
arr.length
可赋值,数组长度可变 -
给数组添empty类型
-
赋值过小会丢失元素
-
取索引值:
arr.indexOf()
-
类型不同数值相同索引值不同
-
arr.slice()
截取数组一部分,返回一个新的数组 -
push()
pup()
-
unshift()
首部插入 -
shift()
首部弹出
-
sort()
排序 -
reverse()
倒置
-
arr.concat()
数组拼接
-
连接符
arr.join()
打印拼接数组,使用特定的输入内容拼接 -
注意:上2并没有修改原来的数组,只是返回了一个新的数组
-
多维数组
七、对象
- JavaScript中的所有键都是字符串,值是任意对象!!!
- 格式:
var 对象名={
属性名:属性值,
属性名:属性值,
属性名:属性值
}
- JavaScript中键值对描述对象属性,多个属性间逗号隔开,最后一个不带逗号
- 对象赋值:使用一个不存在的属性,不会报错,undefined
- 动态的删减属性
delete
- 动态的添加属性:直接给新的属性增加值即可
- 判断属性值是否在对象中
in
,可以判断继承toString
- 判断一个属性是否是这个对象自身拥有的
hasOwnProperty()
八、流程控制
- if-else 同java
- while 同java
<script>
var a=1
while(a<10){
console.log(a);
a++;
}
</script>
- for循环,
fori
自动弹出,let
定义局部变量
foreach
方法循环
<script>
var age=[312,21,332,1,31]
age.forEach(function (value){
console.log(value)
})
</script>
for...in
和for...of
for index in...
这里index是索引值而非元素值
<script>
var age=[312,21,332,1,31]
for(var index in age){//这里index是索引值而非元素值
console.log(index,age[index]);
}
</script>
for _ of...
这里_可以表示元素值
<script>
var arr=[1,2,3,4]
for(_ of arr){
console.log(_);
}
</script>
九、集合Map和Set
- Map
<script>
var map1=new Map([["a",1],["b",2],["c",3]]);
var name1=map1.get("a");//通过key获得value
map1.set("d",4);
console.log(name1);
var name2=map1.get("d");
console.log(name2)
</script>
- Set:无序不重复的集合
<script>
var set1=new Set([1,2,3,3,3])
set1.add(4)
console.log(set1.has(1))
console.log(set1)
</script>
- iterable
<script>
var map1=new Map([["a",33],["b",44],["c",55]]);
for (let x of map1){
console.log(x);
}
</script>
- 注意:一个早期的漏洞
<script>
var arr=[3,4,5]
console.log(arr);
for (let x in arr){
console.log(x);
}
for (let x of arr){
console.log(x);
}
arr.name="2131321";
console.log(arr);
for (let x in arr){
console.log(x);
}
for (let x of arr){
console.log(x);
}
</script>
十、函数
- 定义函数
方法一:
function 方法名(参数值){
...;
...;
return ...
}
方法二:function(参数值){}是一个匿名函数,但可以把结果赋值给方法名,通过方法名调用函数
var 方法名=function(参数值){
...;
...;
return ...
}
方法一和方法二等价
- JavaScript方法可以传入多个参数,也可以不传参数且不报错,需要自定义异常
<script>
function abs(x){
if (typeof x!=='number'){
throw 'Not a number';
}
if (x<0){
return -x;
}else{
return x;
}
}
</script>
arguements
是js免费赠送的关键字,代表传进来的所有参数是一个数组,可以利用这个关键字获取传进来的特定的参数值
<script>
function abs(x) {
console.log("x->", x);
for (let i = 0; i < arguments.length; i++) {
console.log(arguments[i]);
}
if (arguments.length>1){
var target=arguments[1];
console.log("Target:",target)
}
}
</script>
-
问题:arguements包含所有的参数,如何排除已有的参数去使用特定的参数?
-
...rest
获取除已定义的参数外的所有参数,rest
参数放最后,必须用...
标识
以前的操作:
<script>
function a(a,b){
console.log("a:",a);
console.log("b:",b);
if(arguments.length>2) {
for (var i = 2; i < arguments.length; i++) {
}
}
}
</script>
现在的操作:
<script>
function a(a,b,...rest){
console.log("a:",a);
console.log("b:",b);
console.log(rest);
}
</script>
十一、变量作用域
- 在JavaScript中,var定义的变量是有作用域的,在函数体中声明的变量函数外不可用
<script>
function a(){
var x_=1;
function b(){
var y=2;
y=x_+1;//x_可用
}
var z=y+x_;//y不可用
}
</script>
- 假设内部函数变量和外部重名
<script>
function a(){
var x_=1;
function b(){
var x_=2;
console.log("inner x_",x_);
}
console.log("调用内部b()");
b();
console.log("outer x_",x_);
}
</script>
-
注意:假设在JavaScript中函数查找变量从自身函数开始,由"内"向“外"查找,假设外部存在这个同名的函数变量,则内部函数会屏蔽外部函数的变量。|
-
提升变量的作用域
<script>
function a(){
var x="x"+"+"+y;
console.log(x);
var y="y";
}
</script>
等价于
<script>
function a(){
var y;
var x="x"+"+"+y;
console.log(x);
var y="y";
}
</script>
</head>
-
说明:js执行引擎,自动提升了y的声明,但是不会提升y的赋值。建议养成规范,提前声明变量
-
全局对象window----重点
<script>
var x="21"
alert(x);
alert(window.x)//默认所有的全局变量,都会自动绑定在window对象下
window.alert(x);
window.alert(window.x)
</script>
alert()
函数本身也是window的一个变量- Javascript 实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错
RefrenleError
<script>
var old_alert=window.alert;
window.alert=function (){
};
window.alert("12");//无显示
window.alert=old_alert;
window.alert(123);
</script>
十二、规范!
由于我们所有的全局变量都会绑定到我们的window上。如果不同的js文件,使用了相同的全局变量会导致冲突。
解决办法:把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题
<script>
var XZZ={};
XZZ.name='xzz';
XZZ.add=function (a,b){
return a+b;
}
</script>
- jQuery等价于“&”
- 局部作用域
let
<script>
function a(){
for(var i = 0;i<5;i++){
}
console.log(i+1)//出问题,i出了定义域还能使用
}
</script>
改成let
关键字
<script>
function a(){
for(let i = 0;i<5;i++){
}
console.log(i+1)//报错
}
</script>
const
常量,自定义即不可修改,只读变量
<script>
const PI=3.14;
PI = 1;
console.log(PI);
</script>
十三、方法
- 方法就是把函数放在对象的里面,对象只有两个东西:属性和方法
- 调用对象内的方法要带()
Date
方法
<script>
var XZZ={
name:"xzz",
birth:2001,
age:function (){
var now=new Date().getFullYear();//获取今年年份
age=now-this.birth;//this关键字
console.log(age);
}
}
</script>
拆开分解分析
<script>
function getAge(){
var now=new Date().getFullYear();
return now-this.birth;
}
var XZZ={
name:"xzz",
birth:2001,
age:getAge
}
</script>
//getAge() NaN 因为此时this为window对象,不含birth属性
//XZZ.age() ok 因为此时this为XZZ对象,包含birth属性
- 注意:this是无法指向的,是默认指向调用它的那个对象
- 在js中控制this指向,使用方法
apply()
,任何方法都自带这个方法
<script>
function getAge(){
var now=new Date().getFullYear();
return now-this.birth;
}
var XZZ={
name:"xzz",
birth:2001,
age:getAge
}
getAge.apply(XZZ,[])//this指向XZZ,参数为空
</script>
十四、内部对象
Date
时间戳:1970 1.1 0:00:00起的毫秒数:
时间戳转本地时间:
本地时间:toLocaleString()
console.log(now.toLocaleString())
JSON
- JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。它基于 ECMAScript (欧洲计算机协会制定的js规范)的一个子集,采用完全独立于编程语言的文本格式来存储和表示数据。简洁和清晰的层次结构使得 JSON 成为理想的数据交换语言。 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
- 在JavaScript中,一切皆为对象,任何js支持的类型都可以用JSON来表示
- JSON格式:
- 对象都用{}
- 数组都用[]
- 所有键值对都是用 key:value
- js对象转为JSON字符串:
<script>
var user={
name:"XZZ",
age:2,
sex:"nan"
}
var jsonuser=JSON.stringify(user)
</script>
- JSON字符串转为js对象:
<script>
//注意:parse方法内参数为字符串
var user=JSON.parse('{"name":"XZZ","age":2,"sex":"nan"}')
</script>
Ajax
- 原生的js写法 xhr 异步请求
- jQuery 封装好的方法 $("#name").ajax("")
- axios请求
十五、面向对象
原型对象
- 类:模板 原型对象
- 具体实例
- JavaScript不一样
- 原型继承__proto__
<script>
var user={
name:"xzz",
run:function (){
console.log(this.name+" run")
}
}
var Aperson={
name:"duixiang"
}
//原型对象
Aperson.__proto__= user;
</script>
2. class继承
- 定义一个类,属性,方法
<script>
//class定义一个学生类,继承
class Student{
//构造器
constructor(name) {
this.name=name
}
hello(){
console.log("hello"+" "+this.name)
}
}
var student1=new Student("xzz")
student1.hello()
</script>
class littleStudent extends Student{
constructor(name,grade) {
super(name);
this.grade = grade;
}
MyGrade(){
console.log("MyGradeis"+this.grade)
}
}
var ls=new littleStudent("继承","grade")
ls.MyGrade()
ls.hello()
本质是查看对象原型
- 原型链
__proto__
- 简单的回顾一下构造函数、原型和实例的关系:每个构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。那么假如我们让原型对象等于另一个类型的实例,结果会怎样?显然,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立。如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链的基本概念。——摘自《javascript高级程序设计》
- 在JavaScript中,每个函数都有一个prototype属性,这个属性指向函数的原型对象。
- 所以
Object.prototype.__proto__
值为null
十六、操作BOM对象!重点
- BOM浏览器模型
- JavaScript的诞生就是为了在浏览器中运行
window
代表浏览器窗口(重要)
navigator
封装了浏览器的信息
- 大多数时候,不会使用
navigator
对象,,因为会被人为修改 - 不建议用这些属性判断和修改代码
screen
代表屏幕尺寸
<script>
screen.width
screen.height
</script>
location
(重要):代表当前网页的URL信息
host: "localhost:63342"
href: "http://localhost:63342/MyProject1/.idea/1.MyProject1/lesson2…ml?_ijt=se47neoaar5rtmuic1usb2dhfn&_ij_reload=RELOAD_ON_SAVE"
protocol: "http:"
reload:function reload()//刷新网页
location.assign('https://www.bilibili.com/video/BV1JJ41177di?p=19')//设置新的地址
document
代表当前的页面