JavaScript学习
学习前端的要点:
- 视图
- 逻辑
- 事件
- 通信
1、基础语法
-
<script></script>
标签一定是围堵标签,不能是自闭和标签 -
JavaScript严格区分大小写
-
console.log(); 在控制台打印变量,相当于System.out.println();
-
Infinity:无穷大
typeof(Infinity)
> "number"
- NaN六亲不认,任何与NaN进行的判断都为false,只能通过isNaN();来进行判断是否为NaN;
- ==:类型不同,值相同,为true(类型不一致,会先进行类型转换,在判断值)
- ===:类型相同,值相同,为true
NaN === NaN
> false
isNaN(NaN)
> true
1 == "1"
> true
1 === "1"
> false
- 浮点数问题
尽量避免使用浮点数进行运算,存在精度问题!
console.log((1/3) === (1-2/3))
> false
console.log((1/3) - (1-2/3) < 0.00000001)
> true
console.log(1/3)
> 0.3333333333333333
console.log(1 - (2/3))
> 0.33333333333333337
- js中数组下标越界了,不会报异常,是:undefined
- 数组用:[]
- 对象用:{}
原始数据类型:
- number:浮点数、整数、NaN
- string
- null
- boolean:true、false
- undefined
引用数据类型:对象
2、严格检查模式
/*
【前提】:IDEA需要支持 ES6 语法
'use strict':严格检查模式,预防JavaScript的随意性产生的一些问题
局部变量建议都使用 let 去定义~
*/
<script>
'use strict'; // 必须写在第一行,否则浏览器不会报错!
let i = 1;
// 对象的定义
var person = {
"name": "sunzhongjie",
"age": 21,
"tags": ['java', '前端', '运维', 'js']
}
</script>
3、字符串 string
-
正常字符我们使用单双引都可以
-
注意转义字符
/'
/n
/t
console.log("u4e2d") // Unicode字符
> 中
undefined
console.log("x41") // ASCII字符
> A
- 多行字符串编写(Tab上面的键)
var msg = `nihao
HEllo world!
你好!`
- 模板字符串 ${} (ES6的新特性)
'use strict';
let name = "sunzhongjie";
let age = 21;
let msg = `你好,世界,我叫${name},我今年${age}`;
console.log(msg);
// 你好,世界,我叫sunzhongjie,我今年21
- 字符串长度
str.length
- string的不可变性
方法:
- substring():[begin, end)
- charAt(index)
- indexOf(char)
- toUpperCase()
- toLowerCase()
4、数组
Array可以包含任意的数据类型
- indexOf():获取指定元素的索引
- slice():通过下标对数组进行截取
var arr = [1, 2, null, "abc", true];
arr.slice(2);
> [null, "abc", true]
arr.slice(3);
> ["abc", true]
arr.slice(2, 5);
> [null, "abc", true]
arr.indexOf(null);
> 2
- push():压入到尾部
- pop():弹出尾部的一个元素
arr.push("123", 12.2);
> 7
arr
> [1, 2, null, "abc", true, "123", 12.2]
arr.pop();
> 12.2
arr
> [1, 2, null, "abc", true, "123"]
- unshift():压入到头部
- shift():弹出头部的一个元素
arr
> [1, 2, null, "abc", true, "123"]
arr.unshift(undefined, NaN);
> 8
arr
> [undefined, NaN, 1, 2, null, "abc", true, "123"]
arr.shift();
> undefined
arr
> [NaN, 1, 2, null, "abc", true, "123"]
- reverse()
- sort()
arr = new Array("A", "B", "C");
> ["A", "B", "C"]
arr.reverse();
> ["C", "B", "A"]
arr.sort();
> ["A", "B", "C"]
- concat():拼接数组,返回一个新的数组
注意:concat()并没有修改数组,只是返回一个新的数组
arr.concat([1,2,3]);
> ["A", "B", "C", 1, 2, 3]
arr
> ["A", "B", "C"]
- 连接符 join():打印拼接数组,使用特定的字符串连接
arr
> ["A", "B", "C"]
arr.join('#');
> "A#B#C"
5、对象
若干个键值对
对象中的键默认都是 string类型,值可以是任意类型的对象
- 对象的定义(JSON)
'use strict';
let person = {
"name":"sunzhongjie",
"age":21,
"gender":"true"
}
- 动态的删除属性 delete
delete person.gender;
person
> {name: "sunzhongjie", age: 21}
- 动态的添加属性,直接给新属性添加值即可
person.gender = "男";
> "男"
person
> {name: "sunzhongjie", age: 21, gender: "男"}
- 判断这个属性值是否在这个对象中 xxx in xxx
gender in person
VM354:1 Uncaught ReferenceError: gender is not defined
at <anonymous>:1:1
(anonymous) @ VM354:1
"gender" in person
> true
"toString" in person
> true
- 判断一个属性是否是这个对象自身拥有的:hasOwnProperty("参数")
person.hasOwnProperty("name");
> true
person.hasOwnProperty("toString");
> false
6、流程控制
- 判断
'use strict';
let age = 3;
if (age > 2) {
} else if (age < 4) {
} else {
}
- 循环
'use strict';
let arr = [12, 21, 34, 45, 123, 9789, 12390];
// 普通for循环
for (let i = 0; i < arr.length; i++) {
console.log(arr[i]);
}
// forEach循环 (ES 5.1特性)
arr.forEach(function (num) {
console.log(num);
})
// 增强for循环
for (let index in arr) {
console.log(arr[index]);
}
7、Map和Set
ES6的新特性~
var map = new Map([['tom', 20], ['jack', 19]]);
console.log(map.get("tom"));
map.set("admin", "123456");
console.log(map);
var set = new Set([1,2,3,2,2]);
console.log(set);
set.add(5,4);
set.delete(4);
console.log(set);
console.log(set.has(2));
8、Iterator
- 遍历Set和Map
var map = new Map([['tom', 20], ['jack', 19]]);
for (let value of map) {
console.log(value);
}
var set = new Set([1, 2, 3, 2, 2]);
for (let value of set) {
console.log(value);
}
9、可变长参数
问题:arguments 包含所有的参数,我们有时候想使用多余的参数来进行附加操作。
需要排除已有的参数
ES6的新特性:rest
rest参数只能写在最后面,用...
标识
function f(a, b, ...rest) {
console.log("a=>" + a);
console.log("b=>" + b);
console.log("rest=>" + rest);
}
10、变量的作用域
内部函数可以访问外部函数,反之不行!
在JavaScript中,var定义的变量实际是有作用域的。
假设在函数体中声明,则在函数体外不可以使用。
function test() {
var x = 1;
x = x + 1;
}
x = x + 1;
// Uncaught ReferenceError: x is not defined
假设,内部函数变量和外部函数变量,重名!
函数查找变量从自身函数开始,由 “内” 向 “外” 查找
function test() {
var x = 1;
function test2() {
var x = 'a';
console.log('inner:' + x); // inner:a
}
test2();
console.log('outer:' + x); // outer:1
}
test();
提升变量的作用域
function test() {
var x = '1' + y;
console.log(x);
var y = 'y';
}
test();
结果:1undefined
说明:js执行引擎,自动提升了 y 的声明,但是不会提升变量 y 的赋值,相当于
function test() {
var y;
var x = '1' + y;
console.log(x);
y = 'y';
}
test();
这个是在JavaScript建立之初就存在的特性。
养成规范:所有的变量定义都放在函数的头部,不要乱放,便于代码维护;
全局对象:window
var str = "xxx";
alert(str);
window.alert(window.x);
alert()函数本身也是一个 window
的变量
var x = 123;
window.alert(x);
var tmp_alert = alert;
window.alert = function () {
}
window.alert('原先alert失效');
alert = tmp_alert;
window.alert('alert');
JavaScript 实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错:ReferenceError
规范
由于我们所有的全局变量都会绑定到我们的 window 对象上,如果不同的js文件,使用了相同的全局变量,会造成冲突 --> 如何能减少冲突?
// 定义自己的唯一全局变量
var RainSzj = {};
// 赋值
RainSzj.name = "sunzhongjie";
RainSzj.add = function (a, b) {
return a + b;
}
把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突问题。
局部作用域 let
function f() {
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log(i); // 11
}
f();
ES6 let 关键字,解决局部作用域冲突问题!
function f() {
for (let i = 0; i < 10; i++) {
console.log(i);
}
console.log(i);
// Uncaught ReferenceError: i is not defined
}
f();
建议用 let
关键字去定义局部作用域的变量
常量 const
在ES6之前,怎么定义常量:只用用全部大写字母命名的变量就是常量;建议不要修改这样的值。
var PI = 3.1415927;
console.log(PI);
PI = 123; // 但依旧可以修改
console.log(PI);
在ES6中引入了常量关键字:const
;
const PI = 3.1415927;
console.log(PI);
PI = 123; // Uncaught TypeError: Assignment to constant variable.
console.log(PI);
11、方法
定义方法
方法就是把函数放在对象的里面,对象只有两个东西:属性和方法。
var obj = {
'name':'sunzhongjie',
'birth':1999,
'age': function () {
var today = new Date().getFullYear();
return today - this.birth;
}
}
// 调用属性
console.log(obj.name);
// 调用方法,一定要加上括号
console.log(obj.age());
this. 代表什么? 拆开上面的代码
function getAge() {
var today = new Date().getFullYear();
return today - this.birth;
}
var obj = {
'name':'sunzhongjie',
'birth':1999,
'age': getAge // 这里不需要括号
};
谁调用它,谁就是:this
> obj.name;
< "sunzhongjie"
> obj.age;
< ƒ getAge() {
var today = new Date().getFullYear();
return today - this.birth;
}
> obj.age();
< 21
getAge();
< NaN // window
在 Java中,this是无法指向的,是默认指向调用它的那个对象;
apply 函数
是所有的函数公有的
在js中可以控制 this
的指向
function getAge() {
var today = new Date().getFullYear();
return today - this.birth;
}
var obj = {
'name': 'sunzhongjie',
'birth': 1999,
'age': getAge // 这里不需要括号
};
// this 指向了 obj,参数为空
getAge.apply(obj, []);
> getAge.apply(obj, []);
< 21
12、Date对象
typeof 关键字
> typeof 123;
< "number"
> typeof 'adf';
< "string"
> typeof NaN;
< "number"
> typeof undefined;
< "undefined"
> typeof Math;
< "object"
> typeof Math.abs;
< "function"
> typeof {};
< "object"
> typeof [];
< "object"
> typeof Math.abs();
< "number"
基本使用
var now = new Date(); // Mon Jan 20 2020 21:00:20 GMT+0800 (中国标准时间)
now.getFullYear(); // 年
now.getMonth(); // 月 0 ~ 11 月
now.getDate(); // 日
now.getDay(); // 星期几
now.getHours(); // 时
now.getMinutes(); // 分
now.getSeconds(); // 秒
now.getTime(); // 时间戳 全世界统一,自 1970年1月1日 00:00:00 到现在的毫秒数
console.log(new Date(new Date().getTime())); // 事件戳 转为 时间
转换
var time = new Date();
undefined
time;
Mon Jan 20 2020 21:13:22 GMT+0800 (中国标准时间)
time.to
undefined
time.toDateString();
"Mon Jan 20 2020"
time.toGMTString();
"Mon, 20 Jan 2020 13:13:22 GMT"
time.toISOString();
"2020-01-20T13:13:22.165Z"
time.toLocaleString();
"2020/1/20 下午9:13:22"
time.toLocaleTimeString();
"下午9:13:22"
time.toLocaleDateString();
"2020/1/20"
13、JSON对象
JSON是什么?
- JSON(JavaScript Object Notation, JS 对象简谱) 是一种轻量级的数据交换格式。
- 简洁和清晰的层次结构(键值对)使得 JSON 成为理想的数据交换语言。
- 易于人阅读和编写,同时也易于机器解析和生成,并有效地提升网络传输效率。
在JavaScript中,一切皆为对象,任何 js 支持的类型都可以用 JSON来表示;
格式:
- 对象 和 Map用:{}
- 数组和List用:[]
- 所有的键值对,都用
key:value
JS对象与JSON字符串的转换
let user = {
'name': 'sunzhongjie',
'age': 21,
'gender': 'male'
}
// 对象转为JSON字符串
// {"name":"sunzhongjie","age":21,"gender":"male"}
let json_user = JSON.stringify(user);
console.log(json_user);
// JSON字符串转为对象
let obj = JSON.parse('{"name":"sunzhongjie","age":21,"gender":"male"}');
console.log(obj);
14、面向对象编程
类:模板
对象:具体的实例
在JavaScript中,需要换一下思维!
原型
let student = {
name: "zhangsan",
age: 10,
study: function () {
console.log(this.name + ",study....");
}
};
let wu = {
name: "wangwu",
};
// 指定原型对象
wu.__proto__ = student;
class继承
ES6中引入的
- 定义一个类,属性和方法
// 定义一个人类
class Person {
constructor(name) {
this.name = name;
}
eat() {
console.log(this.name + ",我正在吃饭...");
}
}
let person = new Person("张三");
- 继承
// 定义一个学生类
class Student extends Person{
constructor(name, id) {
super(name);
this.id = id;
}
getId() {
console.log(this.name + "的ID是:" + this.id);
}
}
let student = new Student("李华", 100);
原型链,无上限
15、操作BOM对象(重点)
16、操作DOM对象(重点)
核心
浏览器网页就是一个Dom树形结构!
- 更新节点
- 遍历节点
- 删除节点
- 添加节点
要操作一个Dom节点,就必须要先获得这个Dom节点
获得Dom节点
<div class="div">
<h2>h2~~~</h2>
<p id="p1">p1~</p>
<p class="p2">p2~</p>
</div>
// 对应的CSS选择器
let p1 = document.getElementById("p1");
let p2 = document.getElementsByClassName("p2");
let h2 = document.getElementsByTagName("h2");
// 获取父节点下的所有子节点
let divs = document.getElementsByClassName("div")[0];
// divs.firstChild;
// divs.lastChild;
这是原生代码,之后我们都是用 jQuery
更新节点
- innerText:修改文本的值
- innerHTML:可以解析HTML文本标签
删除节点
删除节点的步骤:先获取父节点,再通过父节点删除自己
<div id="father">
<h2>二级标题</h2>
<p id="p1">段落一</p>
<p class="p2">段落二</p>
</div>
<script>
// 删除 段落一 结点
let self = document.getElementById("p1");
let father = p1.parentElement;
father.removeChild(self);
// 删除是一个动态的过程,以下不可取!
father.removeChild(father.children[0]);
father.removeChild(father.children[1]);
father.removeChild(father.children[2]);
</script>
注意:删除多个节点的时候,children 是在时刻变化的,删除节点的时候一定要注意!
插入节点
我们获得了某个DOM节点,假设这个DOM节点是空的,我们通过 innerHTML
就可以增加一个元素,但是如果这个DOM节点已经存在元素了,我们就不能这么干了!会产生覆盖。
<p id="js">JavaScript</p>
<div id="list">
<p id="se">JavaSE</p>
<p id="ee">JavaEE</p>
<p id="me">JavaME</p>
</div>
<script>
// 标签的移动
let list = document.getElementById('list');
let js = document.getElementById('js');
list.appendChild(js);
// 创建一个新的标签
let newP = document.createElement('p');
newP.setAttribute('id', 'Linux');
// newP.id = 'Linux';
newP.innerText = "Linux";
list.appendChild(newP);
// 改变 body 的 background-Color
let body = document.getElementsByTagName("body")[0];
// body.style.backgroundColor = "green";
body.setAttribute("style", "background-color: green;");
</script>
17、操作表单(验证)
- 使用MD5算法进行密码加密,需引入
<!--MD5工具类-->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<!--MD5工具类-->
<script src="https://cdn.bootcss.com/blueimp-md5/2.10.0/js/md5.min.js"></script>
</head>
<body>
<form action="#" method="post" onclick="return check();">
<span>用户名:</span>
<input type="text" name="username" id="username">
<span>密码</span>
<input type="password" id="input-password">
<!--如果不使用隐藏域,提交时,会回显一长串密码-->
<input type="hidden" name="password" id="password">
<input type="submit">
</form>
<script>
function check() {
let uname = document.getElementById('username');
let md5_pwd = document.getElementById('password');
let input_pwd = document.getElementById("input-password");
// pwd.value = md5(pwd.value);
// 提升用户体验
md5_pwd.value = md5(input_pwd.value);
return true;
}
</script>
</body>
</html>
18、jQuery
公式:$(selector).action()
jQuery操作事件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="lib/jquery-3.4.1.js"></script>
</head>
<style>
#divMove {
500px;
height: 500px;
border: 1px solid red;
}
</style>
<script>
// 等待页面加载完成后,响应事件
$(function () {
$('#divMove').mousemove(function (e) {
$('#mouseMove').text('X:' + e.pageX + ', Y:' + e.pageY);
});
});
</script>
<body>
mouse: <span id="mouseMove"></span>
<div id="divMove">
移动鼠标试试!
</div>
</body>
</html>
jQuery操作DOM
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8"/>
<title>jQuery操作DOM</title>
<script src="lib/jquery-3.4.1.js"></script>
</head>
<body>
<ul id="test_ul">
<li id="js">JavaScript</li>
<li name="python">Python</li>
<li name="java">Java</li>
</ul>
<script>
// 属性选择器 获取值
$('#test_ul li[name=python]').text();
// 设置值
$('#test_ul li[name=python]').text('人工智能');
$('#test_ul').html();
// $('#test_ul').html('<strong>123</strong>');
$('#test_ul li[name=python]').css('color', 'red');
</script>
</body>
</html>
元素的显示和隐藏:本质
display:none
$('#test_ul li[name=python]').hide();
$('#test_ul li[name=python]').show();
小技巧
- 如何巩固JS(看jQuery的源码,看游戏源码)
- 巩固HTML、CSS(扒网站,全部down下来,然后对应修改看效果)
好看的前端样式
docsify
ant
友人c
layer:弹窗组件
Element-ui
vuepress