JS 笔记
1. js的作用:
- 表单校验
- 网页特效
- 桌面程序
2. 浏览器执行流程:
-
渲染引擎:解析HTML与CSS的,俗称内核,Chrome的blink -
js引擎:js解释器,读取JavaScript的代码,处理后运行,Chrome的v8引擎 浏览器本身不会执行js,通过内置js引擎来执行js代码,脚本 语言,逐行解释。
3. js 的组成
- ECMAScript js语法
- DOM 页面文档对象模型
- BOM 浏览器对象模型
4. js 的书写位置 (js 里的字符串多用 单引号)
- 行内式
- 内嵌式
- 外部引入
5. 输入输出语句:
- prompt
- alert
- console.log
js变量
1. js 变量
- 当变量只声明不赋值,为undefined
- 当变量不声明而使用,变为全局变量
- 变量命名规范:同 java
2. js 数据类型
-
Number 类型 特殊值:
- Infinity 无穷大
- -Infinity 无穷小
- NaN not a number 不是一个数字 如字符串与数字运算
isNaN() 方法判断是否是非数字 带引号的数字也算 -
String 类型
- str.length 获取字符长度
-
Boolean 类型 与 undefined 与 null
-
flag 可以参与运算 true 为 1 false 为 0 -
小惊喜 undefined 与 null : var str = undefined;
console.log(str + 'zed');
console.log(str + 1);
var str = null;
console.log(str + 'pink');
console.log(str + 1);
-
用 typeof 获取变量的数据类型
-
var v = null;
console.log(typeof(v));
-
prompt 获取的为string类型 -
控制台颜色同样可以判断:黑色为string 蓝色为数字 -
数据类型转换 转字符串的三种方式: var v = 1;
console.log(v);
console.log(v.toString());
console.log(String(v));
console.log(v + '');
转换为数字型的四种方式: console.log(parseInt('2'));
console.log(parseFloat('0.2'));
console.log(Number('3'));
console.log('123' - '3');
转换为布尔类型: 代表为空、否定的值会被转换为false 如:""、0、NaN、null、undefined 其余值转为true ‘0’ 为 true
js运算相关
1. 运算符
var v = 10;
var r = v++ + ++v;
console.log(r);
console.log(v);
== 判断会进行隐式转换,字符转成数字
=== 判断会进行全等判断,判断数据与数据类型
2. 逻辑运算符:
-
布尔值参与逻辑运算 同 java -
非布尔值参与逻辑运算 短路运算(逻辑中断):当左边的表达式可以确定结果将不再进行运算 逻辑与中断: 如果第1个表达式为真,返回表达式2 如果第1个表达式为假,返回表达式1 console.log(12 && 34);
console.log(0 && 2);
console.log('' && 12);
console.log(undefined && 12);
console.log(null && 12);
逻辑或中断: 表达式1结果为真,返回表达式1 表达式1结果为假,返回表达式2 console.log(12 || 34);
console.log(0 || 34);
console.log(null || 12);
console.log(undefined || 12);
var num = 0;
console.log(123 || num++);
console.log(num);
3. 控制语句:
同java
4. 数组
创建数组的方式:
var arr = new Array();
var arr2 = [];
var arr3 = [1, '李四', 'jackson'];
console.log(arr3[3]);
新增元素的方式:
修改 arr.length
var arr = [1, 3, 5];
arr.length = 5;
修改索引号 追加元素 也能直接修改元素
var a = [3, '榴莲', 5];
a[3] = 'pink';
console.log(a);
a[0] = 1;
console.log(a);
5. js 函数
参数问题:
function getSum(num1, num2) {
return num1 + num2;
}
console.log(getSum(1, 2, 3));
console.log(getSum(1));
当函数没有return 则返回undefined
6. arguments 的使用
function getMax() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (max < arguments[i]) {
max = arguments[i];
}
}
return max;
}
console.log(getMax(1, 3, 5, 1, 5, 9));
arguments 是伪数组,不是真正意义上的数组,具有length属性,没有pop() 和 push() 等方法
7. 函数的声明方式
利用函数关键字自定义函数(命名函数)
function fn1() {
console.log(1);
}
fn1();
函数表达式(匿名函数)
var fn = function() {
console.log(1);
}
fn();
8. js 的作用域
js 没有块级作用域,es6 新增块级作用域
if (3 < 5) {
var num = 3;
}
console.log(num);
if (5 < 3) {
var num = 3;
}
console.log(num);
作用域链:
就近查找
预解析:
console.log(num);
var num = 1;
fn();
function fn() {
console.log(1);
}
fn2();
var fn2 = function() {
console.log(1);
}
js 引擎运行分两步:预解析,代码执行
(1)预解析js引擎会把js里的所有var和function 提升到当前作用域的最前面
(2)代码执行 按照代码书写的顺序从上往下执行
预解析分为:变量预解析(变量提升)与函数预解析(函数提升)
(1)变量提升 把所有变量的声明放到当前作用域最前面 不提升赋值操作
(2)函数提升 把所有函数的声明提升到当前作用域最前面 不调用函数
js 预解析 习题:
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num = 10;
fun();
var num = 10;
function fn() {
console.log(num);
var num = 20;
console.log(num);
}
fn();
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
var a = '123';
}
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
9. js 的
创建对象的方法:
-
字面量创建对象 { } var obj = {
name : 'zhangsan',
age : 18,
sayHi : function() {
console.log('Hi');
}
}
console.log(obj.name);
console.log(obj['age']);
obj.sayHi();
-
new 关键字创建对象 var obj = new Object();
obj.name = '李四';
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('Hi~~');
}
console.log(obj.name);
console.log(obj.sex);
console.log(obj['age']);
obj.sayHi();
-
采用构造方法创建对象 同 java function Star(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.sing = function(song) {
console.log(song);
}
}
var obj = new Star('刘德华', 60, '男');
obj.sing('冰雨');
-
遍历对象属性 for……in
function Star(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.sing = function(song) {
console.log(song);
}
}
var obj = new Star('刘德华', 18, '男');
for (var k in obj) {
console.log(k);
console.log(obj[k]);
}
10. js的内置对象
js对象三大类:自定义对象,内置对象,浏览器对象
前两种属于ECMAScript 第三种属于独有的 JS API
查阅MDN官方文档
console.log(Math.PI);
console.log(Math.max(1, 3, 5));
console.log(Math.max());
var myMath = {
PI : Math.PI,
min : function() {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] < min) {
min = arguments[i];
}
}
return min;
},
max : function() {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
}
}
console.log(Math.abs(-1));
console.log(Math.abs('-1'));
console.log(Math.abs('aaa'));
console.log(Math.floor(-1.2));
console.log(Math.floor(1.2));
console.log(Math.ceil(2.1));
console.log(Math.ceil(-1.9));
console.log(Math.round(3.5));
console.log(Math.round(-3.5));
随机数的产生:
function getRandomIntInclusive(min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(Math.random() * (max - min + 1)) + min;
}
创建日期:
var date1 = new Date(2019, 10 ,1);
console.log(date1);
var date2 = new Date('2019-10-1 12:12:12')
console.log(date2);
var now = new Date();
var year = now.getFullYear();
var month = now.getMonth() + 1;
var date = now.getDate();
var arr = ['星期天', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
console.log(year + '年' + month + '月' + date + '日 ' + arr[now.getDay()]);
function getTime() {
var date = new Date("2019-8-8 8:8:8");
var h = date.getHours();
h = h < 10 ? '0' + h : h;
var m = date.getMinutes();
m = m < 10 ? '0' + m : m;
var s = date.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
日期毫秒数:
var date = new Date();
console.log(date.getTime());
console.log(date.valueOf());
var date2 = +new Date();
console.log(Date.now());
function countDown(time) {
var now = +new Date();
var end = +new Date(time);
var times = end - now;
var d = parseInt(times / 1000 / 60 / 60 / 24);
d = d < 10 ? '0' + d : d;
var h = parseInt(times / 1000 / 60 / 60 % 24);
h = h < 10 ? '0' + h : h;
var m = parseInt(times / 1000 / 60 % 60);
m = m < 10 ? '0' + m : m;
var s = parseInt(times / 1000 % 60);
s = s < 10 ? '0' + s : s;
return d + '天' + h + '小时' + m + '分钟' + s + '秒';
}
数组相关:
var arr = [1, 3, 5];
console.log(new Array(2));
console.log(new Array(2, 3));
console.log(arr);
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
console.log(Array.isArray(obj));
var arr = [1, 3, 5];
arr.push(1);
console.log(arr);
arr.unshift(99);
console.log(arr);
arr.pop();
console.log(arr);
arr.shift();
console.log(arr);
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
字符串不可变,同java
字符串的所有方法都不会修改字符串本身(字符串不可变),操作完成都是返回新字符串。
var str = '15795400';
console.log(str.indexOf(5));
console.log(str.indexOf(5, 2));
var str = 'abcoefoxyozzopp';
var index = str.indexOf('o');
var count = 0;
while (index != -1) {
count++;
console.log(index);
index = str.indexOf('o', index + 1);
}
console.log(count);
var str = 'abcoefoxyozzopp';
console.log(str.charAt(0));
console.log(str[0]);
console.log(str.charCodeAt(0));
var str = 'abcoefoxyozzopp';
var obj = {};
for (var i = 0; i < str.length; i++) {
var chars = str[i];
if (obj[chars]) {
obj[chars]++;
} else {
obj[chars] = 1;
}
}
console.log(obj);
var max = 0;
var themax = '';
for (var k in obj) {
if (obj[k] > max) {
max = obj[k]
themax = k;
}
}
console.log(max);
console.log(themax);
字符串操作方法:
var str = '123456789';
console.log(str.substr(3, 3));
var str = '123345369';
while (str.indexOf(3) != -1) {
str = str.replace(3, '*');
}
console.log(str);
var str = 'a, b, c';
console.log(str.split(','));
var str = 'a& b& c';
console.log(str.split('&'));
var str = 'asbDSsdf';
console.log(str.toUpperCase());
console.log(str.toLowerCase());
11. 数据类型
简单数据类型(基本数据类型、值类型)
string, number, boolean, undefined, null
var str = null;
console.log(typeof(str));
WebAPI
1. 获取元素的方法
console.dir( ) 更好的查看属性和方法
var nav = document.getElementById('nav');
var lis = nav.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
console.log(lis[i]);
}
var boxs = document.getElementsByClassName('box');
var box1 = document.querySelector('.box');
console.log(box1);
var box2 = document.querySelector('#b1');
console.log(box2);
var boxs = document.querySelectorAll('.box');
var bodyEle = document.body;
console.log(bodyEle);
var htmlEle = document.documentElement;
console.log(htmlEle);
2. 操作元素
改变元素内容:
div.innerText 不识别html的标签 写的时候原封不动写出,读的时候不显示html标签,取出空格与换行
div.innerHtml 识别html标签 写的时候自动转换标签,读的时候保留原有的所有格式,并保留html标签
仿京东密码栏
// label 标签绑定文本框,点击时鼠标光标移至输入框
<label for="pwd">
<img src="images/open.png" id="eye">
</label>
<input type="password" id="pwd">
改变样式:
div.onclick = function() {
div.style.backgroundColor = 'skyblue';
this.style.width = '300px';
}
div.onclick = function() {
this.className = 'change';
}
排他思想:
- 清除所有元素样式
- 给当前元素设置样式
trs[i].onmouseover = function() {
this.style.backgroundColor = 'pink';
}
trs[i].onmouseout = function() {
this.style.backgroundColor = '';
}
表单全选与反选:
for (var i = 0; i < checkboxs.length; i++) {
checkboxs[i].onclick = function() {
for (var i = 0; i < checkboxs.length; i++) {
if (!checkboxs[i].checked) {
btn.checked = false;
return;
}
}
btn.checked = true;
}
}
属性的获取
<div id="dd" indexsss="one"></div>
console.log(div.id);
console.log(div.getAttribute('id'));
console.log(div.indexsss);
console.log(div.getAttribute('indexsss'));
属性的设置
var div = document.querySelector('div');
div.setAttribute('indexsss', 'tow');
div.setAttribute('class', 'more');
div.removeAttribute('class');
自定义属性
目的:保存使用数据,直接保存到页面中而不用保存到数据库中。
设置自定义属性:规定以 data- 开头
获取自定义属性:
- element.getAttribute(‘data-index’)
- element.dadaset.index 或者 element.dataset[‘index’] (ie11 才开始支持)
<div data-index="1"></div>
<div data-index="2"></div>
<div data-index-time="3"></div>
var divs = document.querySelectorAll('div');
console.log(divs[1].dataset.index);
console.log(divs[0].dataset['index']);
console.log(divs[2].dataset.indexTime);
3. 操作节点
? 利用父子兄弟节点关系获取元素,逻辑性强但兼容性差。
节点概述:
? 节点至少拥有nodeType、nodeName、nodeValue三个基本属性。
nodeType:
- 元素节点 nodeType 为 1
- 属性节点 nodeType 为 2
- 文本节点 nodeType 为 3(包含文字、空格、换行)
相关节点的方法:
ul.childNodes;
for (var i = 0; i < ul.childNodes.length; i++) {
if (ul.childNodes[i].nodeType == 1) {
console.log(ul.childNodes[i]);
}
}
parentNode.children;
node.parentNode;
console.log(ol.firstChild);
console.log(ol.lastChild);
console.log(ol.firstElementChild);
console.log(ol.lastElementChild);
console.log(ol.children[0]);
console.log(ol.children[ol.children.length - 1]);
for (var i = 0; i < lis.length; i++) {
lis[i].onmouseover = function() {
this.children[1].style = 'display: block';
}
lis[i].onmouseout = function() {
this.children[1].style = 'display: none';
}
}
console.log(div.nextSibling);
console.log(span.previousSibling);
console.log(div.nextElementSibling);
console.log(span.previousElementSibling);
function getNextElementSibling(element) {
var el = element;
while (el = el.nextSibling) {
if (el.nodeType == 1) {
return el;
}
}
return null;
}
创建与添加、删除节点:
var li = document.createElement('li');
var ul = document.querySelector('ul');
ul.appendChild(li);
ul.insertBefore(li, ul.children[0]);
ul.removeChild(ul.children[0]);
<a href='javascript:;'>删除</a>
var c1 = ul.children[0].cloneNode();
ul.appendChild(c1);
var c2 = ul.children[0].cloneNode(true);
ul.appendChild(c2)
三种创建元素方式的区别:
document.write('<div>12</div>');
var arr = [];
for (var i = 0; i < 5000; i++) {
arr[i] = '<a href="#">百度</a>';
}
div.innerHTML = arr.join('');
for (var i = 0; i < 5000; i++) {
var a = document.createElement('a');
div.appendChild(a);
}
事件高级
1. 注册与解绑
传统的注册事件 on
var btn = document.querySelector('button');
btn.onclick = function() {
alert('这是什么')
}
btn.onclick = function() {
alert('这是2')
}
监听注册事件 addEventListener
eventTarget.addEventListener(type, listener[, useCapture])
btn.attachEvent('onclick', function() {
alert('123');
})
btn.attachEvent('onclick', function() {
alert('456');
})
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uVfiPXDX-1636552441568)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211105102521068.png)]
解绑事件
btn.addEventListener('click', fn)
function fn() {
alert('按钮被点击');
btn.removeEventListener('click', fn);
}
btn.onclick = function() {
alert('按钮被电机');
btn.onclick = null;
}
btn.attachEvent('onclick', fn);
function fn() {
alert('123');
btn.detachEvent('onclick', fn);
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TIsQSh0r-1636552441572)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211106164926294.png)]
2. DOM事件流
捕获:事件监听从大到小,document -> html -> body -> div 逐渐下沉
冒泡:事件监听从小到大 div -> body -> html -> document 逐渐冒泡
注意:
- js代码中只能执行捕获或冒泡中的一个阶段
- onclick 与 attachEvent 只能得到冒泡阶段
- addEventListener(type, listener[, useCapture])第三个参数是true,表示捕获。不写默认为false,表示冒泡。
- 有些事件没有冒泡,如 onblur, onfocus, onmouseover, onmouseleave
var son = document.querySelector('.son');
son.addEventListener('click', function() {
console.log(1);
}, false);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
console.log(2);
}, false);
var son = document.querySelector('.son');
son.addEventListener('click', function() {
console.log(1);
}, true);
var father = document.querySelector('.father');
father.addEventListener('click', function() {
console.log(2);
}, true);
事件对象
var btn = document.querySelector('button');
btn.onclick = function(event) {
console.log(event);
}
window.event;
var ul = document.querySelector('ul');
ul.addEventListener('click', function(e) {
console.log(this);
console.log(e.target);
})
e.srcElement
a.addEventListener('click', function(e) {
e.preventDefault();
})
a.onclick = function(e) {
e.preventDefault();
e.returnValue;
return fales;
}
e.stopPropagation();
e.cancelBubble = true;
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
})
document.addEventListener('selectstart', function(e) {
e.preventDefault();
})
事件委托的原理:
不给每个子节点单独设置事件监听器,而是利用冒泡原理,在父节点上添加监听器。
ul.addEventListener('click', function(e) {
alert('弹出对话框');
e.target.style.backgroundColor = 'pink';
})
常用鼠标事件
document.addEventListener('click', function(e) {
console.log(e.clientX);
console.log(e.clientY);
console.log('----------------');
console.log(e.pageX);
console.log(e.pageY);
console.log('----------------');
console.log(e.screenX);
console.log(e.screenY);
})
var img = document.querySelector('img');
document.addEventListener('mousemove', function(e) {
var x = e.pageX;
var y = e.pageY;
img.style.top = y + 'px';
img.style.left = x + 'px';
})
键盘事件:
document.addEventListener('keydown', function(e) {
console.log(1);
})
document.addEventListener('keypress', function(e) {
console.log(1);
})
document.addEventListener('keyup', function(e) {
console.log(1);
})
document.addEventListener('keyup', function(e) {
console.log(e.keyCode);
})
document.addEventListener('keypress', function(e) {
console.log(e.keyCode);
})
BOM 相关
- 他是js访问浏览器窗口的一个接口。
- 他是一个全局对象,定义在全局作用域中的变量、函数都会变成window对象的属性和方法。
window.onload = function () {
}
window.addEventListener('load', function() {
})
document.addEventListener('DOMContentLoaded', function() {
})
window.addEventListener('resize', function(){
console.log(window.innerWidth);
})
1. 定时器
window.setTimeout (调用函数, [延迟的毫秒数]);
setTimeout(function() {
alert('时间到了');
}, 2000);
setTimeout(boom, 2000);
function boom() {
alert('爆炸了');
}
var timer1 = setTimeout(function() {
console.log(1);
}, 2000);
var timer2 = setTimeout(function() {
console.log(2);
}, 3000);
var timer1 = setTimeout(function() {
alert('爆炸');
}, 5000);
var btn = document.querySelector('button');
btn.onclick = function() {
clearTimeout(timer1);
}
setInterval(回调函数,[间隔的毫秒数]);
每隔一段时间调用一次函数。
setInterval(countDown, 1000);
var timer = null;
bt1.addEventListener('click', function() {
timer = setInterval(function() {
console.log(1);
}, 500);
})
bt2.addEventListener('click', function() {
clearInterval(timer);
})
this 指向问题
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
var o = {
sayHi: function() {
console.log(this);
}
}
o.sayHi();
var btn = document.querySelector('button');
btn.onclick = function() {
console.log(this);
}
btn.addEventListener('click', function() {
console.log(this);
})
function Fun() {
console.log(this);
}
var fun = new Fun();
js 执行机制
js 是单线程的
为了解决这个问题,H5 提出 web worker 标准,允许 js 脚本创建多个线程,于是 js 出现了同步和异步
同步任务:都在主线上执行,形成一个执行栈
异步任务:通过回调函数实现
- 普通事件 如 click、resize 等
- 资源加载 如 load、error 等
- 定时器 报告 setInterval、setTimeout 等
js 执行机制:
- 先执行执行栈中的同步任务 。
- 异步任务放入任务队列。
- 一旦同步任务执行完成,就会按次序读取任务队列中的异步任务,进入执行栈,开始执行。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-3Uj1Djyo-1636552441574)(C:\Users\Administrator\AppData\Roaming\Typora\typora-user-images\image-20211110124412253.png)]
核心:异步进程处理
1. location、navigator、history
location 对象
location 对象属性 | 返回值 |
---|
location.href | 获取或者设置 整个URL | location.host | 返回主机(域名) | location.port | 返回端口号 没写则返回空 | location.pathname | 返回路径 | location.search | 返回参数 | location.hash | 返回片段 #后面内容 常见于链接锚点 |
locatioin 对象的方法
location 对象的方法 | 返回值 |
---|
locaiton.assign() | 与href一样,可以跳转页面 | locatioin.replace() | 替换当前页面,不记录历史 | location.reload() | 重新加载页面,相当于刷新按钮或F5 如果参数为true 强制刷新ctrl+F5 (消除缓存) |
navigator 对象
包含有关浏览器的信息,有很多信息,最常用的是userAgent,该属性可以返回客户机发送服务器的user-agent头部的值。
history 对象
history 对象方法 | 作用 |
---|
back() | 可以后退功能 | forward() | 前进功能 | go(参数) | 1 是前进 -1 是后退 数值任意 |
2. offset、client、scroll
offset 偏移量 使用offset 系列相关属性可以动态的得到该元素的位置、大小
- 获得元素距带有定位的父元素的位置
- 获得元素自身的大小(宽度高度)
- 注意:返回的数值都不带单位
console.log(son.offsetParent);
console.log(son.offsetTop);
console.log(son.offsetWidth);
console.log(son.offsetHeight);
offset 与 style 的区别
-
offset 可以获得任意样式表的样式值,style 只能获取行内样式 -
offset 是不带单位的数字,style 是带单位的字符串 -
offset 包含padding、border,style 不包含 -
offset 只读,style 能修改
总结:offset 读, style 写
|