技术标签: 前端 es6 javascript
目录
抛出自定义错误
<!DOCTYPE html>
<html>
<body>
<p>Please input a number between 5 and 10:</p>
<input id="demo" type="text">
<button type="button" onclick="myFunction()">Test Input</button>
<p id="message"></p>
<script>
function myFunction() {
var message, x;
message = document.getElementById("message");
message.innerHTML = "";
x = document.getElementById("demo").value;
try {
if(x == "") throw "is Empty";
if(isNaN(x)) throw "not a number";
if(x > 10) throw "too high";
if(x < 5) throw "too low";
}
catch(err) {
message.innerHTML = "Input " + err;
}
}
</script>
</body>
</html>
try里面放可能会出错误的代码 catch是当发生错误时执行的,且有参数,代表错误本身,finally表示不管有没有错误都会执行
<body>
<p>123</p>
<script>
try{
let ss = document.querySelector('.p');//Cannot read properties of null (reading 'style')
ss.style.color = 'red'
}catch(err){
console.log(err.message);
}finally{
alert('sdasda')
}
</script>
</body>
浅拷贝与深拷贝都只针对 引用类型
浅拷贝拷贝的是值(其实也是地址)
<script>
const obj={
age :18
}
let o = {...obj}
let o1={}
Object.assign(o1,obj)
o1.age=20
console.log(o1);//age =20
console.log(obj);//age =18
</script>
</body>
但是这样有问题:
const obj={
age :18,
obj1:{
sex:1
}
}
let o = {...obj}
let o1={}
Object.assign(o1,obj)
o1.obj1.sex = 2
console.log(o1);
console.log(obj);//sex都为2
欠拷贝只直接拷贝最外一层的值,而对于obj1来说,最外层的值是他的地址,所以就直接把地址给了o1,改变o1时也会改变obj
直接拷贝对象 不是地址
设置函数,当originValue里面还有引用数据类型时,再次调用自己,只是将originValue改为里面的引用数据类型
<script>
const obj = {
uname: 'pink',
age: 18,
hobby: [{ name: 2222, age: 2222 }, '足球',new Set([123, 22, 333])],
family: {
baby: '小pink'
},
run: function () {
console.log(1);
},
sete: new Set([123, 22, 333]),
asas:Symbol('asd')
}
obj.self = obj
function deepcopy1(originValue,map = new WeakMap()){
if(typeof originValue === 'symobol'){
return new Symbol(originValue.desciption)
}
if(!(originValue instanceof Object)){
return originValue
}
if(typeof originValue === 'function'){//函数不需要深拷贝
return originValue
}
if(originValue instanceof Set){
const newSet = new Set()
for(let item of originValue){
newSet.add(deepcopy1(item,map))
}
return newSet
}
if(map.get(originValue)){//当我遍历到self,self需要我自身,也就是obj,这里直接把map中的obj拿给他
return map.get(originValue)
}
let newobj = originValue instanceof Array?[]:{} //如果originValue是单纯的对象或数组
map.set(originValue,newobj)
for(let key in originValue){
newobj[key] = deepcopy1(originValue[key],map)
}
return newobj
}
let ss = deepcopy1(obj)
console.log(ss);
</script>
这里比较难的地方在于 obj.self = obj ,也就是在obj中创造了self指向自己
在深拷贝时,传入map = new WeakMap()用于记录已经生成的应用对象,当拷贝到self时,这个时候又需要创造一个obj对象,这时可以将map中存储好的obj直接拿出来赋值给它
先去下载库,并引入js
Lodash 简介 | Lodash 中文文档 | Lodash 中文网
调用cloneDeep()
var oo = _.cloneDeep(obj)
console.log(oo);
<script>
const obj = {
uname: 'pink',
age: 18,
hobby: ['乒乓球', '足球'],
family: {
baby: '小pink'
}
}
// JSON.stringify(obj)
//将对象转换为JSON字符串
let o =JSON.parse(JSON.stringify(obj))//将JSON字符串转换为对象
</script>
但是JSON有个问题,如果 对象有 函数 或者 symbol 则无法解析
可以改变this指向,在调用的时候用,第一个值就是设置指向
let obj={
}
function fn(x,y){
console.log(this);
}
fn.call(obj,1,2)//obj
也是改变this指向 ,类似,传参必须为数组,这个用的比较多
let obj={
}
function fn(x,y){
console.log(this);//obj
console.log(x+y);//3
}
fn.apply(obj,[1,2])
值得注意的是,当不匹配时:
let obj={
}
function fn(x){
console.log(this);//obj
console.log(x);//1
}
fn.apply(obj,[1,2])
不会将数组全部传入
提供了另外一种求最大值的方式
let aa = [1,4,5,8,9]
//Math.max(1,4,7,98)
console.log(Math.max(...aa));
console.log(Math.max.apply(null,aa));
前面两种都必须要调用函数,这个不需要,返回值是函数,其实就是改变原函数的this得到了一个新函数
let aa = [1,4,5,8,9]
function fn(){
console.log(this);
}
fn.bind(null)//无输出
let fun = fn.bind(aa);
fun()//a
小应用,点击按钮禁用,两秒开启
<button>点击禁用,两秒开启</button>
<script>
let btn = document.querySelector('button');
btn.addEventListener('click',function(){
this.disabled = true
setTimeout(function(){
this.disabled = false
}.bind(this),2000)
})
</script>
这个地方把定时器的this改为了btn,因为bind(this)里面这个this还是btn
在一定的时间内只能执行一次,不管触发了多少次,在这个时间内只执行一次
例子:div滑动时,200ms内只改变span一次
var start = 0
document.querySelector('div').addEventListener('mousemove',function(){
let now = Date.now()
if(now-start>=200){
document.querySelector('span').innerHTML =i++
start = now
}
})
每次调用函数时都将此时的时间赋给now,当now与start差别大于200毫秒时才会改变i,然后将现在的时间赋给start以进行下次函数
上面用的是时间差值的方法,也可以采用定时器的方法
这里再加了一个immediate 变量,具体原理参照 防抖
<body>
<input type="text">
<button>cancel</button>
<button class="throttle">throttle</button>
<script>
let ipt = document.querySelector('input')
let mythrottle = function(fn,interval,immediate =true){
let timeout = null
let immediate_done = false
let _throttle = function(){
if (!immediate_done && immediate) {
fn.apply(this)
immediate_done = true
return
}
if(!timeout){
timeout = setTimeout(()=>{
fn.apply(this)
timeout = null
},interval)
}
}
return _throttle
}
ipt.addEventListener('input',mythrottle(function(){
console.log(this.value);
},1000))
</script>
触发后n秒内只执行一次,但是如果这段时间内还触发了,则会重新计算时间
也就是说,在一定时间内我不停的进行高速的事件触发,但是只会在最后一次触发结束后进行执行
应用场景:输入框,一般是等我输入完了才会去匹配
例子:在div滑动时 停下来一秒钟才会改变span
document.querySelector('div').addEventListener('mousemove',function(){
if(timeget) clearTimeout(timeget)
timeget = setTimeout(function(){
document.querySelector('span').innerHTML =i++
},1000)
})
例子:再次采用函数实现,需求是对输入框,输入结束一段时间后反应,这里还提供了应该取消接口,可以在这段时间结束前 结束响应
<input type="text">
<button>cancel</button>
<script>
let mydebounce = function(fn,delay){
let timeout = null
let _debounce = function(){
if(timeout) clearTimeout(timeout)
timeout = setTimeout(()=>{
fn.apply(this)
},delay)
}
_debounce.cancel = function(){
if(timeout) clearTimeout(timeout)
}
return _debounce
}
let ipt = document.querySelector('input')
let btn = document.querySelector('button')
let debounce = mydebounce(function(){
console.log(this.value);
},2000)
ipt.addEventListener('input',debounce)
btn.addEventListener('click',debounce.cancel)
</script>
</body>
再加一个立即执行功能,即在输入时,第一次输入马上响应,后面输入则等待一段时间,然后再次输入又马上响应
let mydebounce = function(fn,delay,immediate=false){
let timeout = null
let immediate_done = false
let _debounce = function(){
if(timeout) clearTimeout(timeout)
if(!immediate_done && immediate){
fn.apply(this)
immediate_done = true
return
}
timeout = setTimeout(()=>{
fn.apply(this)
immediate_done = false
},delay)
}
_debounce.cancel = function(){
if(timeout) clearTimeout(timeout)
immediate_done = false
}
return _debounce
}
定义了 immediate表示是否需要这个功能,immediate_done判断是否完成,当输入时,immediate为1,immediate_done为0时,会马上执行fn函数,然后使得immediate_done为1。在执行完时间间隔后,又将immediate_done为0
还可以将_debounce函数返回为promise,好处是在fn传入时有返回值的情况下,可以拿到这个返回值
let res = null
let _debounce = function () {
return new Promise((resolve, reject)=>{
if (timeout) clearTimeout(timeout)
if (!immediate_done && immediate) {
res = fn.apply(this)
resolve(res)
immediate_done = true
return
}
timeout = setTimeout(() => {
res = fn.apply(this)
resolve(res)
immediate_done = false
}, delay)
})
}
若fn有返回值,就可以通过.then得到
let ipt = document.querySelector('input')
let btn = document.querySelector('button')
let debounce = mydebounce(function () {
console.log(this.value);
return(111)
}, 1000)
ipt.addEventListener('input', debounce)
btn.addEventListener('click', debounce.cancel)
debounce().then(res=>{
console.log(res);
})
还可以使用lodash
节流
_.throttle(fn,300)
在300ms内只能执行一次fn函数
function fn(){
document.querySelector('span').innerHTML =i++
}
document.querySelector('div').addEventListener('mousemove',_.throttle(fn,300))
防抖
_.debounce(fn,300)
停下来300ms后才执行fn函数
function fn(){
document.querySelector('span').innerHTML =i++
}
document.querySelector('div').addEventListener('mousemove',_.debounce(fn,300))
const video = document.querySelector('video')
video.onloadeddata = function(){
video.currentTime = localStorage.getItem('time')||0
}
video.ontimeupdate = _.throttle(function(){
localStorage.setItem('time',video.currentTime)
},1000)
得到video视频
每次打开页面都把存储中的time拿出来,赋值给视频的currentTime,即跳转到对应的时间
视频的时间发生改变时,添加防抖,每隔1s更新存储中的time值
实现每次页面打开可以返回上次视频播放的地方
当项目中有很多组件,很多文件,当一个文件中的某一个事件触发,希望另外一个文件得到响应,就需要用到事件总线
这里我们自己用js实现
一般来说这个事件总线是一个对象,里面有emit函数,用于发送时间,也有on函数,用于接受事件
<button>aaaa</button>
<script>
class EventBus{
constructor(){
this.eventMap = {}//这个map用于存储on绑定的函数
}
on(eventname,fn){
let fns = this.eventMap[eventname]
if(!fns){//第一次如果没有函数数组时,自己创造一个
fns=[]
this.eventMap[eventname] = fns
}
fns.push(fn)//将回调函数放入对应的函数数组
}
emit(eventname,...args){
let fns = this.eventMap[eventname]
if(!fns) return
fns.forEach(fn => {
fn(...args)
});
}
}
let eventBus = new EventBus()
eventBus.on('btnclick',()=>{
console.log(1111);
})
eventBus.on('btnclick',()=>{
console.log(2222);
})
let btn = document.querySelector('button')
btn.addEventListener('click',function(){
console.log('自己得到');
eventBus.emit('btnclick')
})
</script>
因为on函数,对于一种事件的响应函数可能不止一个,所以需要eventMap来存储函数,其数据结构为{ eventname:[fn1,fn2]}
在emit时,先取得事件对应的函数数组,再以此执行
还可以写一个删除函数函数
off(eventname,fn){
let fns = this.eventMap[eventname]
if (!fns) return
for(let i=0;i<fns.length;i++){
if(fn === fns[i]){
fns.splice(i,1)
break
}
}
//如果fns已经被清空了,那直接将事件删除
if(fns.length==0){
delete this.eventMap[eventname]
}
}
前言前两天测试Lua接收C++函数的参数时,发现number、boolean、string都没有什么问题,但是userdata和lightuserdata有什么区别呢?于是测试了一下,我们来看看结果...
对于回归而言,更注重的是模型拟合的曲线,相对于真实曲线的误差。主要包括:拟合优度/R-Squared,校正决定系数(Adjusted R-square),均方误差(MSE),均方根误差(RMSE),误差平方和(SSE),平均绝对误差(MAE),平均绝对百分比误差(MAPE)。1、均方误差(MSE)均方误差是指:观测值与真值偏差的平方和与观测次数的比值公式:MSE相当于模型中的损失函数,线性回归过程中尽量让该损失函数最小。那么模型之间的对比也可以用它来比较。MSE可以评价模型的预测精度,MSE的值越
一个小小的Strust2例子然后发现css,js,图片用不了,debugger下发现无法访问这些资源(404错误),妈的,那个例子明明可以的,起码从书上的图片看。发现是web.xml中的过滤器的问题,代码是这样的:web.xml<?xml version="1.0" encoding="UTF-8"?><web-app xmlns="http:/...
1.某报表处理系统,要求用户输入处理报表的日期。系统规定日期由年、月的六位数字字符组成,前四位代表年,后两位代表月。设日期限制在1990年1月至1999年12月,即系统只能对该段时期内的报表进行处理。如果用户输入的日期不在此范围内,则显示输入错误。现用等价类划分法设计测试用例,来测试程序的日期检查功能。...
回顾大二这一学年,不同于大一的单调色彩,大二我所经历的是非常丰富多彩的,尽管也很会遇到一些不如意的事情,有心酸,有遗憾,有愤慨,有无奈;但是我也遇到了一些非常有趣的人和事,懂得了一些只有经历才能明白的道理。我清楚地知道生活不应只有苦难,更多还有来自平凡之人、之物的感动,欣喜,还有希望。一路顺风的人生并不完美,也不可能有这样的人生。技术的追求与探索、会长的责任与担当、爱情的憧憬、梦想的追逐、现实的愤慨与无奈、平凡之人、之物的感动.......这一切的一切共同拼接成了我的大二生活,有苦有乐,有起有伏
Name: ‘CREATE TABLE’ Description:该语句用于创建 table。 语法:CREATE [EXTERNAL] TABLE [IF NOT EXISTS] [database.]table_name(column_definition1[, column_definition2, …][, index_definition1[, ndex_definition12,]])[ENGINE = [olap|mysql|broker|hive]][key_desc][COM
eclipse 项目编译后文件位置
android记事本项目----原型已经基本完成
注:file:指项目根目录(项目名下)。classpath指类的根目录(src/main/resources)
1、限幅滤波法(又称程序判断滤波法)/*A、名称:限幅滤波法(又称程序判断滤波法)B、方法: 根据经验判断,确定两次采样允许的最大偏差值(设为A), 每次检测到新值时判断: 如果本次值与上次值之差 如果本次值与上次值之差>A,则本次值无效,放弃本次值,用上次值代替本次值。C、优点: 能有效克服因偶然因素引起的脉冲干扰。D、缺
文件结构 . ├── BlusterCritter │ ├── BlusterCritter.java │ └── BlusterCritterRunner.java ├── ChameleonKid │ ├── ChameleonKid.java │ └── ChameleonKidRunner.java ├── KingCrab │ ├── KingCrab.java │ └── KingCrabRunner.java ├── ModifiedChamele
1.类型推导2.nullptr指针空值3.基于范围的for循环4.typedef与using5.新增容器