数据类型
基本数据类型:String, Boolean,Number,null,undefined 这5种之外的类型都称为Object
引用数据类型:Object, function, Array
区别:
- 基本: 简单数据类型。变量保存在栈内存中, 比较两个基本数据类型的值本质是比较值
- 引用: 对象数据类型。对象保存在堆内存中, 变量保存的是对象的内存地址.比较两个引用的本质是比较对象的内存地址
undefined:未赋值或未定义的变量值均为undefined
null:定义一个空对象
== 与 === 区别
1、对于 string、number 等基础类型,== 和 === 是有区别的
a)不同类型间比较,== 之比较 “转化成同一类型后的值” 看 “值” 是否相等,=== 如果类型不同,其结果就是不等。
b)同类型比较,直接进行 “值” 比较,两者结果一样。
2、对于 Array,Object 等高级类型,== 和 === 是没有区别的
null 与 undefined 区别
1)undefined:是所有没有赋值变量的默认值,自动赋值。
2)null:主动释放一个变量引用的对象,表示一个变量不再指向任何对象地址。
2、何时使用null
当使用完一个比较大的对象时,需要对其进行释放内存时,设置为 null。
3、null 与 undefined 的异同点
共同点:都是原始类型,保存在栈中变量本地。
不同点:
(1)undefined——表示变量声明过但并未赋过值。它是所有未赋值变量默认值,例如:var a; // a 自动被赋值为 undefined
(2)null——表示一个变量将来可能指向一个对象。一般用于主动释放指向对象的引用
作用域
- let声明后的变量不允许在同一作用域中重新声明,不同作用域可以重新声明
- 用var声明的是全局变量
- 使用const声明的是常量,值无法改变
var关键字定义的变量可以先使用后声明。(变量提升)
let关键字定义的变量需要先声明再使用,全局声明的变量不存在于window对象中(与var不同)。
const关键字定义的常量,声明时必须进行初始化,且初始化后不可再修改。
类型检测
- typeof:返回原始数据类型
- instanceof:检测构造函数的prototype属性是否出现在某个实例对象的原型链上
String
将其他数值转换为字符串有三种方式:toString()、String()、
拼串。
String 对象属性
constructor 对创建该对象的函数的引用
length 字符串的长度
prototype 允许您向对象添加属性和方法
String.toUpperCase .toLowerCase
.trim():删除字符串左右的空白字符
stringObject.charAt(index)
.charAt(i):获取第i个字符
stringObject.indexOf(searchvalue,fromindex)
.indexOf('i'):获取字符i的位置
.indexOf('o',2):从第2个字符开始搜索o的位置
.lastIndexOf('i'):从结尾搜索字符串位置
stringObject.match(searchvalue)
stringObject.match(regexp)
stringObject.search(regexp)
.search("com"):搜索子字符串"com"的位置
.includes('i'):判断字符串中是否包含i
.startsWith('h'):判断字符串是否为h开头
.endsWith('com'):判断字符串是否为com结束
stringObject.replace(regexp/substr,replacement)
.replace("i","j"):用j替换i
.split(""):将字符串中的每个字符以""分隔
stringObject.split(separator,howmany)
.split(","):将字符串转换为数组
.toString():转换为字符串
截取字符串:slice,substr,substring
stringObject.slice(start,end)允许负数作为参数
stringObject.substr(start,length)
stringObject.substring(start,stop)
slice(i),substr(i),substring(i): 从第i个开始截取
console.log(hd.slice(3)); //dunren.com
console.log(hd.substr(3)); //dunren.com
console.log(hd.substring(3)); //dunren.com
slice(i,j),substring(i,j):截取第i到第j个
substr(i,j)从第i个开始截取,共截取j个字符
console.log(hd.slice(3, 6)); //dun
console.log(hd.substring(3, 6)); //dun
console.log(hd.substring(3, 0)); //hou 较小的做为起始位置
console.log(hd.substr(3, 6)); //dunren
Number
把非数值转换为数值:Number()、parseInt()
和parseFloat()。parseInt()只会将字符串转换为整数,而parseFloat()可以转换
为浮点数。
Number.isInteger(i):判断是否为整数
Number.isNaN(i):判断是否NAN
parseInt(' 99hj'):提取字符串中数字
Math.max.apply(Math, [1, 2, 3]):在数组中取最大值
Math.ceil(1.11):取最接近的向上整数
Math.floor(1.11):取最接近的向下整数
Math.round(1.11):四舍五入
Math.random()*5:返回0-5的随机数,不包括5
Math.random()*(5+1):返回0-5的随机数,包括5
min+Math.floor(Math.random()*(Max-min)):取min-max的随机数
Array
Array 对象属性
constructor 返回对创建此对象的数组函数的引用。
length 设置或返回数组中元素的数目。
prototype 使您有能力向对象添加属性和方法。
Array.isArray([]):检测是否为数组类型
([1,2,3]).toString():转换为字符串1,2,3
([1,2,3]).join("-"):转换为字符串1-2-3
Array.from(str):将类数组转换为数组
...将数组展开,可用于合并数组
.push('1'):压入新元素1,返回值为数组元素数量
.pop():弹出末尾元素,返回值为被弹出的元素
.shift():从数组前面取出元素,返回值为被取出的元素
.unshift():从数组前面添加元素,返回值为数组元素数量
.fill("a"):使用a填充数组元素
arrayObject.slice(start,end) start必需
.slice():获取数组所有元素
.slice(1,2):从数组中截取1-2的元素合成新元素
arrayObject.splice(index,howmany,item1,.....,itemX) index,howmany必需
.splice(1,3):从第一个元素开始删,一共删3个元素,返回值为被删除的元素
.splice(1,3,'rr'):删掉从第一个开始的三个元素,在删除位置添加rr
.splice(arr.length,0,'kk'):在末尾添加kk
.splice(0,0,'k'):在开头添加k
合并拆分
.join('-'):使用-连接数组内元素为字符串
.split(","):使用,将字符串分割数组
.concat(a,b):连接数组a和b
.copyWithin(target,start,end)
查找元素
.indexOf(i):返回i出现的位置
.lastIndexOf(i):从后向前找
.includes(i):返回布尔值
.find(i):返回第一次找到的值,若找不到则返回undefined,可以查找引用类型
.findIndex(i):返回索引值
数组排序
.reverse():反转
Array.sort((a,b)=>a-b):返回负数则a排在b前面,从小到大
循环遍历
.forEach(item,index,array)
for i in array 每次循环取索引i
for item of array 每次循环取值
for(const [key,value] of array.entries())遍历获取索引和值
arr.keys():获取索引
arr.values():获取值
arr.entries():获取键值对
扩展方法
.every(user => user.js >= 60):递归检测元素,所有都为真才返回true
.some(function (item, index, array) {
return title.indexOf(item) >= 0;
}):有一个为真就返回true
.filter(function (item, index, array) {
if (item.category.toLowerCase() == 'css') {
return true;
}
}):过滤数据中元素
.map(item => item.title):在数组的所有元素上应用函数,用于映射出新的值
.reduce:迭代数组的所有元素
第一个参数是执行函数,第二个参数为初始值
arr.reduce((previousValue, currentValue, currentIndex, array) => {}, initialValue?)
reduce 为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受四个参数:初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
参数 说明
prev 上次调用回调函数返回的结果
cur 当前的元素值
index 当前的索引
array 原数组
array.reduce((total, cur) => (total += cur == elem ? 1 : 0), 0);
}统计元素出现的次数
array.reduce(
(max, elem) => (max > elem ? max : elem), array[0]
);取数组中的最大值
array.reduce((goods, elem) => {
if (elem.price > price) {
goods.push(elem);
}
return goods;
}, []).map(elem => elem.name);获取价格超过1万的商品名称
arr.reduce((pre, cur, index, array) => {
if (pre.includes(cur) === false) {
pre = [...pre, cur];
}
return pre;
}, []) 使用 reduce 实现数组去重
/**
* 用数组的reduce方法实现数组的map
*/
Array.prototype._map = function(fn, thisArg) {
const result = [];
this.reduce((prev, curr, index, array) => {
result[index] = fn.call(thisArg, array[index], index, array);
}, 0)
return result;
Set
移除Set中大于5的数值
let hd = new Set("123456789");
hd=new Set([...hd].filter(item=>item<5))
去除字符串重复
console.log([...new Set("hdsiss")].join(""));
去除数组重复
console.log(...new Set(arr));
交集
let hd = new Set(['hdcms', 'houdunren']);
let cms = new Set(['后盾人', 'hdcms']);
let newSet=new Set(
[...hd].filter(item=>cms.has(item)));
let newSet=[...hds,...cms];求并集
WeakSet结构同样不会存储重复的值,它的成员必须只能是对象类型的值。是弱引用
WeakMap 对象是一组键/值对的集
键名必须是对象
WeaMap对键名是弱引用的,键值是正常引用
函数
如何调用(执行)函数?
- test()
- new test()
- obj.test()
- test.call/apply(obj)
标准声明优先级高于赋值声明
function hd(num) {
return ++num;
} 优先级更高,console.log(hd(3))为4
var hd = function() {
return "hd";变量函数定义不会被提升
};
默认参数
function avg(total, year = 1) {
return Math.round(total / year);
}
console.log(avg(2000, 3));
当不传递year参数时,year的取值为默认值1
arguments 是函数获得到所有参数集合
function sum() {
return [...arguments].reduce((total, num) => {
return (total += num);
}, 0);
}
展开语法
let [a, b, c] = [...hd];
function hd(...args) {
console.log(args);
}
使用 ... 可以接受传入的多个参数合并为数组
构造函数主要用来生成对象,里面的this默认就是指当前对象
使用箭头函数后 this 为定义该函数的上下文,也可以理解为定义时父作用域中的this. this 总是指向调用该函数的对象
改变构造函数中的空对象,即让构造函数this指向到另一个对象
- call与apply 用于显示的设置函数的上下文,两个方法作用一样都是将对象绑定到this,只是在传递参数上有所不同。
- bind()是将函数绑定到某个对象,bind是复制函数行为比如 a.bind(hd) 可以理解为将a函数绑定到hd对象上即
hd.a(),使用bind会生成新函数 - apply 用数组传参call 需要分别传参
- call/apply 会立即执行函数,bind不会立即执行
call()和apply()都可以指定一个函数的运行环境对象,就是设置函数执行时的this值
– 函数对象.call(this对象,参数数组)
– 函数对象.apply(this对象,参数1,参数2,参数N)
常见的回调函数
- DOM事件函数
var btn = document.getElementById('btn')
btn.onclick = function () {
alert(this.innerHTML)
}
- 定时器函数
setInterval(function () {
alert('到点啦!')
}, 2000)
- ajax回调函数
- 生命周期回调函数
作用域
子函数被外部使用父级环境将被保留
使用 let/const 可以将变量声明在块作用域中, 在 for 循环中使用let/const 会在每一次迭代中重新生成不同的变量
JS中的所有函数都是闭包
闭包一般在子函数本身作用域以外执行,即延伸作用域
闭包特性中上级作用域会为函数保存数据,从而造成内存泄漏问题
使用箭头函数可以解决函数因为是在全局环境下调用的,所以this指向window的问题
对象
创建对象有两种方式:
var person = new Object();
person.name = "孙悟空";
person.age = 18;
var person = {
name:"孙悟空",
age:18
};
访问属性的两种方式:
.访问 对象.属性名
[]访问 对象[‘属性名’]
什么时候必须使用[‘属性名’]的方式?
- 属性名不是合法的标识名
- 属性名不确定
Object.keys 返回一个所有元素为字符串的数组,其元素来自于从给定的object上面可直接枚举的属性。这些属性的顺序与手动遍历该对象属性时的一致
定义在对象中的函数我们称为方法
使用…可以展示对象的结构
对象转换:如果声明需要字符串类型,调用顺序为 toString > valueOf 如果场景需要数值类型,调用顺序为 valueOf > toString
属性管理:
hasOwnProperty检测对象自身是否包含指定的属性,不检测原型链上继承的属性
let obj = { name: '后盾人'};
console.log(obj.hasOwnProperty('name')); //true
使用 in 可以在原型对象上检测
console.log(arr.hasOwnProperty("length")); //true
console.log(arr.hasOwnProperty("concat")); //false
console.log("concat" in arr); //true
Object.assign设置属性
使用for/in遍历对象属性
for/of用于遍历迭代对象
同时获取属性名与值
for (const array of Object.entries(hd)) {
console.log(array);
}
Object.assign 函数可简单的实现浅拷贝,它是将两个对象的属性叠加后面对象属性会覆盖前面对象同名属性。
代理(拦截器)是对象的访问控制,setter/getter 是对单个对象属性的控制,而代理是对整个对象的控制
使用 JSON.parse 将字符串 json 解析成对象
原型
在构造函数中存在着一个名为原型的(prototype)对象,这个对象中保存着一些属性,凡是通过该构造函数创建的对象都可以访问存在于原型中的属性
每个函数都有一个prototype属性, 它默认指向一个对象原型对象
原型对象中有一个属性constructor, 它指向函数对象
console.log(Date.prototype.constructor===Date) true
console.log(fn.prototype.constructor===fn) true
- 每个函数function都有一个prototype,即显式原型
- 每个实例对象都有一个__proto__,可称为隐式原型
- 对象的隐式原型的值为其对应构造函数的显式原型的值
- 函数的prototype属性: 在定义函数时自动添加的, 默认值是一个空Object对象
- 对象的__proto__属性: 创建对象时自动添加的, 默认值为构造函数的prototype属性值
function Fn() {
}
var fn = new Fn()
console.log(Fn.prototype, fn.__proto__)
console.log(Fn.prototype===fn.__proto__)
VM901:5 {constructor: ƒ} {constructor: ƒ}
VM901:6 true
程序员能直接操作显式原型
Fn.prototype.test = function () {
console.log('test()')
}
fn.test() test()
获取原型对象
– 构造函数. prototype
– Object.getPrototypeOf(对象)
– 对象._ proto_
– 对象. constructor.prototype
原型链 别名: 隐式原型链 作用: 查找对象的属性(方法)
每个对象都有原型对象,原型对象也有原型对象。对象,和对象的原型,以及原型的原型,就构成了一个原型链
当从一个对象中获取属性时,会首先从当前对象属性中查找,如果没有则顺着__proto__查找,直到找到Object对象的原型位置,找到则返回,找不到则返回undefined。
读取对象的属性值时: 会自动到原型链中查找
设置对象的属性值时: 不会查找原型链, 如果当前对象中没有此属性, 直接添加此属性并设置其值
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.setName = function (name) {
this.name = name; 方法一般定义在原型中
}
Person.prototype.sex = '男'; 属性一般通过构造函数定义在对象本身上
原型是一个指向对象的指针,可以将原型理解为对象的父亲,对象从原型对象继承来属性.使用原型对象为多个对象共享属性或方法
原型包含 constructor 属性,指向构造函数
对象包含 __proto__
指向他的原型对象
使用原型可以解决,通过构建函数创建对象时复制多个函数造成的内存占用问题
函数拥有多个原型,prototype 用于实例对象使用,__proto__
用于函数对象使用
function User() {}
User.__proto__.view = function() {
console.log("User function view method");
};
User.view();
User.prototype.show = function() {
console.log("后盾人");
};
let hd = new User();
hd.show();
console.log(User.prototype == hd.__proto__);
创建对象时构造函数把原型赋予对象
function User() {}
let xj = new User();
console.log(xj.__proto__ == User.prototype);
表达式: A instanceof B
- 如果B函数的显式原型对象在A对象的原型链上, 返回true, 否则返回false
Function是通过new自己产生的实例
function Foo() { }
var f1 = new Foo();
console.log(f1 instanceof Foo); true
console.log(f1 instanceof Object); true
使用 setPrototypeOf 与 getPrototypeOf 设置和获取原型
constructor存在于prototype原型中,用于指向构建函数的引用
instanceof 检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上
使用isPrototypeOf检测一个对象是否是另一个对象的原型链中
使用in 检测原型链上是否存在属性,使用 hasOwnProperty 只检测当前对象
使用 for/in 遍历时同时会遍历原型上的属性
使用 call 或 apply 可以借用其他原型方法完成功能
let hd = {
data: [1, 2, 3, 4, 5]
};
Object.setPrototypeOf(hd, {
max: function() {
return this.data.sort((a, b) => b - a)[0];
}
});
console.log(hd.max());
let xj = {
lessons: { js: 100, php: 78, node: 78, linux: 125 },
get data() {
return Object.values(this.lessons);
}
};
console.log(hd.__proto__.max.apply(xj));
this 不受原型继承影响,this 指向调用属性时使用的对象
let hd = {
name: "后盾人"
};
let houdunren = {
name: "向军",
show() {
return this.name;
}
};
hd.__proto__ = houdunren;
console.log(hd.show());后盾人
函数默认prototype 指包含一个属性 constructor 的对象,constructor 指向当前构造函数
使用Object.create创建一个新对象时使用现有对象做为新对象的原型对象
在实例化对象上存在 __proto__
记录了原型,所以可以通过对象访问到原型的属性或方法
__proto__
不是对象属性,理解为prototype 的 getter/setter 实现,他是一个非标准定义
__proto__
内部使用getter/setter 控制值,所以只允许对象或null
建议使用 Object.setPrototypeOf 与Object.getProttoeypOf 替代 __proto__
使用 in 会检测原型与对象,而 hasOwnProperty 只检测对象,所以结合后可判断属性是否在原型中
function User() {
}
User.prototype.name = "后盾人";
const lisi = new User();
//in会在原型中检测
console.log("name" in lisi);true
//hasOwnProperty 检测对象属性
console.log(lisi.hasOwnProperty("name"));false
使用 prototype 更改构造函数原型,使用 Object.setPrototypeOf 与 Object.getPrototypeOf 获取或设置原型。
Object.create 创建对象时指定原型
__proto__
声明自定义的非标准属性设置原型,解决之前通过 Object.create 定义原型,而没提供获取方法
Object.setPrototypeOf 设置对象原型
构造函数在被new 时把构造函数的原型(prototype)赋值给新对象。如果对象中存在属性将使用对象属性,不再原型上查找方法
当对象中没有可以使用的属性时,JS会从原型上获取这就是继承在JavaScript中的实现
通过构造函数创建对象
function Admin() {}
console.log(Admin == Admin.prototype.constructor); //true
let hd = new Admin.prototype.constructor();
console.log(hd);
let xj = new Admin();
console.log(xj);
多态
根据多种不同的形态产生不同的结果,下而会根据不同形态的对象得到了不同的结果
继承是为了复用代码,继承的本质是将原型指向到另一个对象
JS不能实现多继承,如果要使用多个类的方法时可以使用mixin混合模式来完成。
使用 isPrototypeOf 判断一个对象是否在另一个对象的原型链中
正则表达式
直接量语法
/pattern/attributes
创建 RegExp 对象的语法:
new RegExp(pattern, attributes);
/正则表达式/修饰符(可选)
参数 pattern 是一个字符串,指定了正则表达式的模式或其他正则表达式。
参数 attributes 是一个可选的字符串,包含属性 “g”、“i” 和 “m”,分别用于指定全局匹配、区分大小写的匹配和多行匹配。
-
修饰符:i(执行大小写不敏感的匹配), g(全局匹配), m(多行匹配)
-
[] 只匹配其中的一个原子
[^] 只匹配"除了"其中字符的任意一个原子
[0-9] 匹配0-9任何一个数字
[a-z] 匹配小写a-z任何一个字母 -
\d(查找数字),\s(查找空白字符),\b(匹配单词边界) n+(匹配至少包含一个n的字符串),
n*(包含零或多个n的字符串),n?(包含零或一个的字符 -
^ 匹配字符串的开始 $ 匹配字符串的结束,忽略换行符
-
/是正则表达式开始和结束的标志,\将后面的字符标记为特殊字符
<p>替换"k1"为"k2"</p>
<button onclick="f1()">Click me</button>
<p id="demo">请访问k1</p>
<script>
function f1(){
var str=document.getElementById("demo").innerHTML;
var txt=str.replace("k1","k2");
document.getElementById("demo").innerHTML= txt;}
</script>
使用${}实现变量和字符串的拼接
if(window.confirm(`hello${this.name}`))
创建数组:
var i;
var cars=new Array();
cars[0]="a";
cars[1]="b";
cars[2]="c";
for(i=0;i<cars.length;i++)
document.write(cars[i]+"<br>");
创建对象:
var people=new Object();
people.name='Tim';
people.age=17;
people.eat=function(){}
添加删除数组项:
- 作用在数组末尾:push()/pop() 调用后返回数组新长度/返回已被删除的部分
- 作用在数组开头:unshift(),shift()
字符串方法
charAt(), concat(), indexOf(), lastIndexOf(), localeCompare(), match(),split(), splice(), substr(), substring(), toString(), tpUpperCase(),
trim(), valueOf()
DOM
选取节点
节点:Node——构成HTML文档最基本的单元。
• 常用节点分为四类
– 文档节点document:整个HTML文档
– 元素节点Element:HTML文档中的HTML标签
– 属性节点Attr:元素的属性
– 文本节点Text:HTML标签中的文本内容
获取元素节点• 通过document对象调用
1. getElementById()
– 通过id属性获取一个元素节点对象
2. getElementsByTagName()
– 通过标签名获取一组元素节点对象
3. getElementsByName()
– 通过name属性获取一组元素节点对象
获取元素节点的子节点 • 通过具体的元素节点调用
1. getElementsByTagName()
– 方法,返回当前节点的指定标签名后代节点
2. childNodes
– 属性,表示当前节点的所有子节点
3. firstChild
– 属性,表示当前节点的第一个子节点
4. lastChild
– 属性,表示当前节点的最后一个子节点
获取父节点和兄弟节点 • 通过具体的节点调用
1. parentNode
– 属性,表示当前节点的父节点
2. previousSibling
– 属性,表示当前节点的前一个兄弟节点
3. nextSibling
– 属性,表示当前节点的后一个兄弟节点
属性
• nodeValue
– 文本节点可以通过nodeValue属性获取和设置文本节点的内容
• innerHTML
– 元素节点通过该属性获取和设置标签内部的html代码
使用CSS选择器进行查询
querySelector() querySelectorAll()
• 都是用document对象来调用,都是传递一个选择器字符串作为参数,方法会自动根据选择器字符串去网页中查找元素。
• querySelector()只会返回找到的第一个元素,而querySelectorAll()会返回所有符合条件的元素。
document.getElementById(id)
getElementByName('name') 获取设置了name属性的元素
getElementsByTagName用于按标签名获取元素
getElementsByClassName用于按class 样式属性值获取元素集合
querySelectorAll根据CSS选择器获取Nodelist节点列表
querySelector使用CSS选择器获取一个元素
const app = document.getElementById('app')
const nodes = [...app.querySelectorAll('li')].filter((node) => {
return !node.matches(`[name]`)
})
console.log(nodes)
使用getElement…返回的都是HTMLCollection动态的集合
使用querySelectorAll返回的是NodeList静态集合
节点的修改
指对元素节点的操作
• 创建节点
– document.createElement(标签名)
• 删除节点
– 父节点.removeChild(子节点)
• 替换节点
– 父节点.replaceChild(新节点 , 旧节点)
• 插入节点
– 父节点.appendChild(子节点)
– 父节点.insertBefore(新节点 , 旧节点)
显示数据
- window.alert()弹出窗口
- document.write()将内容写入HTML文档中
document.write(Date());
- innerHTML写入HTML元素中
<p id="a">k</p>
<script>
document.getElementById("a").innerHTML="kkk";
</script>
- console.log()将内容写入控制台
JavaScript计算器
```javascript
<table border="1" style="position: center ;">
<tr><td>第一个数</td><td>
<input type="text" id="first" /></td></tr>
<tr><td>第二个数</td>
<td><input type="text" id="second" /></td> </tr>
<tr><td colspan="2">
<button onclick="sum()">+</button>
<button onclick="substract()">-</button>
<button onclick="f()">*</button>
<button onclick="divide()">/</button></td></tr>
<tr><td colspan="2">
<p id="result">结果是:</p> </td></tr>
</table>
<script>
function getFirst(){
var f=document.getElementById("first").value;
return f;
}
function getSecond(){
var s=document.getElementById("second").value;
return s;
}
function sendResult(r){ // 给p标签传值
var n=document.getElementById("result");
n.innerHTML=r;
}
function sum()
{
var a=getFirst();
var b=getSecond();
var r=Number(a)+Number(b); // 不转换为数字的话结果就是两个字符串的连接
sendResult(r);
}
function substract()
{
var a=getFirst();
var b=getSecond();
var r=a-b;
sendResult(r);
}
</script>
全选/全不选
```javascript
1<input type="checkbox" name="c" value=1/><br>
2<input type="checkbox" name="c" value=2/><br>
3<input type="checkbox" name="c" value=3/><br>
4<input type="checkbox" name="c" value=4/>
<input type="button" value="全选" onclick="allcheck(this)"/>
<script>
var checkAll=false;
function allcheck(e)
{
checkAll=!checkAll;
e.value=checkAll ? "全选" : "全不选";
let inputs=document.getElementsByName('c');
for(var index in inputs)
inputs[index].checked=checkAll;
}
JavaScript表单验证
验证输入
<p>请输入1-10的数字</p>
<input id="num" />
<button onclick="check()">提交</button>
<p id="demo"></p>
<script>
function check(){
var x,text;
x=document.getElementById("num").value;
if(isNaN(x)||x<1||x>10)
text="输入错误";
else text="输入正确";
document.getElementById("demo").innerHTML=text;
}
</script>
this 的多种指向:
1、在对象方法中, this 指向调用它所在方法的对象。
2、单独使用 this,它指向全局(Global)对象。
3、函数使用中,this 指向函数的所属者。
4、严格模式下函数是没有绑定到 this 上,这时候 this 是 undefined。
5、在 HTML 事件句柄中,this 指向了接收事件的 HTML 元素。
6、apply 和 call 允许切换函数执行的上下文环境(context),即 this 绑定的对象,可以将 this 引用到任何对象。
事件
为一个元素绑定事件处理程序:
– 通过HTML元素指定事件属性来绑定
– 通过DOM对象指定的属性来绑定
– 设置事件监听器 元素对象.addEventListener() 需要两个参数:事件字符串,响应函数
事件的传播
• 捕获阶段
– 这一阶段会从window对象开始向下一直遍历到目标对象,如果发现有对
象绑定了响应事件则做相应的处理。
• 目标阶段
– 这一阶段已经遍历结束,则会执行目标对象上绑定的响应函数。
• 事件冒泡阶段
– 这一阶段,事件的传播方式和捕获阶段正好相反,会从事件目标一直向
上遍历,直至window对象结束,这时对象上绑定的响应函数也会执行。
取消事件传播
• 可以使用event对象的两个方法完成:
– stopPropagation()
– stopImmediatePropagation()
• 取消默认行为:
– preventDefault()
HTML事件:onchange, onclick, onload, onmouseover, onkeydown
改变HTML:
- document.write() // 改变输出流
- document.getElementById(id).innerHTML=新HTML // 改变HTML元素内容
- document.getElementById(id).attribute=新属性值 // 改变HTML元素属性
改变CSS:
- document.getElementById(id).style.property=新样式
HTML事件属性
- 向HTML元素分配事件
<Button onclick="displayDate()">Click me</Button>
- 使用HTML DOM分配事件
<script>document.getElementById("bst").onclick=function(){ displayDate();}}</script>
EventListener
Element.addEventListener(event, function);
event:事件类型,如click/mousedown,
function:事件触发后调用的函数,
element.addEventListener("mouseover", myFunction);
element.addEventListener("click", mySecondFunction);
element.addEventListener("mouseout", myThirdFunction);
x=document.getElementById(id)为null导致addEventListener无法使用时,可加上window.onload
window.onload = function () {
var x = document.getElementById("myBt");
x.addEventListener("click", myFunction);
};
JavaScript HTML DOM 元素
- appendChild() // 创建新的HTML节点
<div id="d">
<p id="p1">p1</p></div>
<script>
var para=document.createElement("p"); // 创建<p>元素
var node=document.createTextNode("p'");// 为<p>元素创建一个新的文本节点
para.appendChild(node); // 将该文本节点添加到<p>元素中
var e=document.getElementById("d"); // 查找已存在的元素
e.appendChild(para); // 将<p>元素添加到该元素中
</script>
- 将新元素添加到开始位置处:insertBefore()
- 移除已存在的元素,需知道其父元素 parent.removeChild(child)
- 替换 HTML 元素 - replaceChild()
<div id="d">
<p id="p1">p1</p>
<p id="p2">p2</p></div>
<script>
var para=document.createElement("p");
var node=document.createTextNode("p3");
para.appendChild(node);
var parent=document.getElementById("d");
var child=document.getElementById("p1");
parent.replaceChild(para, child); // 用p3的值替换p1的值
</script>
闭包
闭包是一个函数引用另一个函数的变量,提供了一个在外部访问另一个函数内部局部变量的方式,不必要的闭包只会增加内存消耗。
设置计数器递增:
<p>局部变量计数</p>
<button onclick="f1()">计数</button>
<p id="p">0</p>
<script>
var add =(function(){
var count=0; // 从外部访问该局部变量count,保证其递增
return function(){
return count+=1;
}
})();
function f1(){
document.getElementById("p").innerHTML=add();
}
</script>
BOM(浏览器对象模型)
超时调用:
– setTimeout()
– 超过一定时间以后执行指定函数
– 需要连个参数:
• 要执行的内容
• 超过的时间
• 取消超时调用
– clearTimeout()
• 超时调用都是在全局作用域中执行的。
间歇调用
• 间歇调用:
– setInterval()
– 每隔一段时间执行指定代码
– 需要两个参数:
• 要执行的代码
• 间隔的时间
• 取消间隔调用:
– clearInterval()
弹窗
- 警告框:window.alert(“text”);
- 确认框:window.confirm(“text”);
- 提示框:window.prompt(“text”,“defaultvalue”);
Promise
Promise 将异步操作队列化,按照期望的顺序执行,返回符合预期的结果。一个 promise 必须有一个 then 方法用于处理状态改变
Promise包含pending、fulfilled、rejected三种状态
- pending 指初始等待状态,初始化 promise 时的状态
- resolve 指已经解决,将 promise 状态设置为fulfilled
- reject 指拒绝处理,将 promise 状态设置为rejected
- promise 是生产者,通过 resolve 与 reject 函数告之结果
- promise 创建时即立即执行即同步任务,then 会放在异步微任务中执行,需要等同步任务执行后才执行。then是对返回promise的处理
如果 resolve 参数是一个 promise ,将会改变promise状态.当promise做为参数传递时,需要等待promise执行完才可以继承
链式调用
每次的 then 都是一个全新的 promise,默认 then 返回的 promise 状态是 fulfilled
catch用于失败状态的处理函数,等同于 then(null,reject){}
扩展接口
- resolve 使用 promise.resolve 方法可以快速的返回一个promise对象
- reject 生成一个失败的promise
- 使用Promise.all 方法可以同时执行多个并行异步操作
- allSettled 用于处理多个promise ,只关注执行完成,不关注是否全部执行成功,allSettled 状态只会是fulfilled
- 使用Promise.race() 处理容错异步,和race单词一样哪个Promise快用哪个,哪个先返回用哪个
任务管理
宏任务指执行栈中待执行的任务(主线程上的同步任务), 包括 script(整体代码)、setTimeout、setInterval
微任务指当前任务执行之后立即执行的任务, 包括 Promise.then
任务的执行顺序是同步任务、微任务、宏任务
事件运行机制:
执行一个宏任务;
遇到微任务,放到微任务列队;
宏任务执行完毕,执行微任务列队中的任务;
微任务执行完毕后,GUI 线程接管,开始渲染页面;
渲染完成后,JS线程继续接管,开启下一个宏任务
Promise 内的任务为立即执行任务,也可以理解为同步任务。而 then 方法中的任务是微任务,会放在微任务列表中
setTimeout(() => console.log(4));
new Promise(resolve => {
resolve();
console.log(1);
}).then(_ => {
console.log(3);
});
console.log(2);
1 2 3 4
Promise.then 是典型的微任务,实例化 Promise 时执行的代码是同步的,便then注册的回调函数是异步微任务的。主线程中的任务执行完后,才执行队列中的任务。有新任务到来时会将其放入队列,采取先进先执行的策略执行队列中的任务