首页 文章 精选 留言 我的

精选列表

搜索[javascript],共9002篇文章
优秀的个人博客,低调大师

JavaScript之Promise对象

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了 Promise 对象。 Promise 对象是一个代理对象(代理一个值),被代理的值在 Promise 对象创建时可能是未知的。它允许你为异步操作的成功和失败分别绑定相应的处理方法(handlers)。 这让异步方法可以像同步方法那样返回值,但并不是立即返回最终执行结果,而是一个能代表未来出现的结果的 Promise 对象。 Promise 对象有以下两个特点: 对象的状态不受外界影响。Promise 对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功) 和 rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。 Promise 对象的状态改变,只有两种可能:从 pending 变为 fulfilled 和 从 pending 变为 rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。如果改变已经发生了,你再对 Promise 对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。 基本用法 new Promise( function(resolve, reject) {...} /* executor */ ); Promise 对象的初始化接收一个执行函数 executor,executor 是带有 resolve 和 reject 两个参数的函数 。 Promise 构造函数执行时会立即调用 executor 函数, resolve 和 reject 两个函数作为参数传递给 executor(executor 函数在 Promise 构造函数返回新建对象前被调用)。 resolve 和 reject 函数被调用时,分别将 promise 的状态改为 fulfilled(完成) 或 rejected(失败)。executor 内部通常会执行一些异步操作,一旦完成,可以调用 resolve 函数来将 promise 状态改成 fulfilled,或者在发生错误时将它的状态改为 rejected。 如果在 executor 函数中抛出一个错误,那么该 promise 状态为 rejected。executor函数的返回值被忽略。 先看个示例:(注:后文的示例均使用 setTimeout 模拟异步操作) // 从 pending 变为 fulfilled var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); resolve('promise fulfilled!'); }, 500); }).then(function(data) { console.log(data); }); // Hi, // promise fulfilled! // 从 pending 变为 rejected var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); reject('promise rejected!'); }, 500); }).then(null, function(error) { console.log(error); //欢迎加入全栈开发交流圈一起学习交流:864305860 }); //面向1-3年前端人员 // Hi, //帮助突破技术瓶颈,提升思维能力 // promise rejected! 从 pending 变为 fulfilled 这段代码,当执行 new Promise() 时,传入的执行函数就立即执行了,此时其内部有一个异步操作(过 500ms 之后执行),等过了 500ms 之后先执行 console.log('Hi,'); 输出 Hi,,此时 promise 的状态为 pending(进行中),而执行 resolve('Promise!'); 则修改 promise 的状态为 fulfilled(完成),然后我们调用 then() 接收 promise 在 fulfilled 状态下传递的值,此时输出 'Promise!'。 同理,从 pending 变为 rejected 这段代码基本差不多,不同的是异步操作调用了 reject 方法,then 方法使用第二个参数接收 rejected 状态下传递的值。 Promise.prototype.then() then 的作用是为 Promise 实例添加状态改变时的回调函数。 then 方法的第一个参数是 resolved 状态的回调函数,第二个参数(可选)是 rejected 状态的回调函数。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }, function(error) { console.log(error); }); // 如果调用 resolve 方法,输出如下: // Hi, // promise fulfilled! // 如果调用 reject 方法,输出如下: // Hi, // promise rejected! then 方法返回的是一个新的 Promise 实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即 then 方法后面再调用另一个 then 方法。采用链式的 then,可以指定一组按照次序调用的回调函数。这时,前一个回调函数,有可能返回的还是一个 Promise 对象(即有异步操作),这时后一个回调函数,就会等待该 Promise 对象的状态发生变化,才会被调用。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); resolve(); }, 500); }).then(function() { return new Promise(function(resolve, reject) { setTimeout(function() { // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }); }) }).then(function(data) { console.log(data); //欢迎加入全栈开发交流圈一起学习交流:864305860 }, function(error) { //面向1-3年前端人员 console.log(error); //帮助突破技术瓶颈,提升思维能力 }); // 如果第一个 then 调用 resolve 方法,第二个 then 调用第一个回调函数,最终输出如下: // Hi, // promise fulfilled! // 如果第一个 then 调用 reject 方法,第二个 then 调用第一个回调函数,最终输出如下: // Hi, // promise rejected! Promise.prototype.catch() catch 方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。 所以下面代码: var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }, function(error) { console.log(error); }); 等价于: var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }).catch(function(error) { console.log(error); }); 如果没有使用 catch 方法或者 then 第二个参数指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码,即不会有任何反应,这跟传统的 try/catch 代码块是不同。 catch 方法返回的还是一个 Promise 对象,因此后面还可以接着调用 then 方法。 catch 方法与 .then(null, rejection) 的不同: 如果异步操作抛出错误,状态就会变为 rejected,就会调用 catch 方法指定的回调函数,处理这个错误。 then 方法指定的回调函数,如果运行中抛出错误,也会被 catch 方法捕获。 catch 方法的写法更接近同步的写法(try/catch)。 因此,建议总是使用 catch 方法,而不使用 then 方法的第二个参数。 Promise.prototype.finally() finally 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。 var p = new Promise(function(resolve, reject) { setTimeout(function() { console.log('Hi,'); // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('promise fulfilled!'); } else { reject('promise rejected!'); } }, 500); }).then(function(data) { console.log(data); }).catch(function(error) { console.log(error); }).finally(function() { console.log('I am finally!'); }); 上面代码中,不管 promise 最后的状态,在执行完 then 或 catch 指定的回调函数以后,都会执行 finally 方法指定的回调函数。 Promise.all() Promise.all 方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。 var p = Promise.all([p1, p2]); 上面代码中,Promise.all 方法接受一个数组作为参数,p1、p2 都是 Promise 实例,如果不是,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。(Promise.all方法的参数可以不是数组,但必须具有 Iterator 接口,且返回的每个成员都是 Promise 实例。) p的状态由p1、p2决定,分成两种情况。 只有 p1、p2 的状态都变成 fulfilled,p 的状态才会变成 fulfilled,此时 p1、p2 的返回值组成一个数组,传递给 p 的回调函数。 只要 p1、p2 之中有一个被 rejected,p 的状态就变成 rejected,此时第一个被 reject 的实例的返回值,会传递给 p 的回调函数。 示例: 试想一个页面聊天系统,我们需要从两个不同的 URL 分别获得用户的个人信息和好友列表,这两个任务是可以并行执行的,用Promise.all()实现。 // 并行执行异步任务 var p1 = new Promise(function (resolve, reject) { setTimeout(function() { // 模拟请求,请求状态为200代表成功,不是200代表失败 if (status === 200) { resolve('P1'); } else { reject('error'); } }, 500); }); var p2 = new Promise(function (resolve, reject) { setTimeout(resolve, 600, 'P2'); }); // 同时执行p1和p2,并在它们都完成后执行then: Promise.all([p1, p2]).then(function (results) { console.log(results); // 输出:['P1', 'P2'] }).catch(function(error) { console.log(error); // 如果p1执行失败,则输出:error }); 注意,如果作为参数的 Promise 实例,自己定义了 catch 方法,那么它一旦被 rejected,并不会触发 Promise.all() 的 catch 方法。 Promise.race() Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。 var p = Promise.race([p1, p2]); 上面代码中,只要 p1、p2 之中有一个实例率先改变状态,p 的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给 p 的回调函数。 Promise.race 方法的参数与 Promise.all 方法一样,如果不是 Promise 实例,就会先调用下面讲到的 Promise.resolve 方法,将参数转为 Promise 实例,再进一步处理。 示例: 有些时候,多个异步任务是为了容错。比如,同时向两个 URL 读取用户的个人信息,只需要获得先返回的结果即可。这种情况下,用Promise.race()实现。 // 多任务容错 var p1 = new Promise(function (resolve, reject) { setTimeout(resolve, 500, 'P1'); }); var p2 = new Promise(function (resolve, reject) { setTimeout(resolve, 400, 'P2'); }); Promise.race([p1, p2]).then(function (result) { console.log(result); // 'P2' }); Promise.resolve() 有时需要将现有对象转为 Promise 对象,Promise.resolve 方法就起到这个作用。 Promise.resolve方法的参数分成四种情况: (1)参数是一个 Promise 实例 如果参数是 Promise 实例,那么Promise.resolve将不做任何修改、原封不动地返回这个实例。 (2)参数是一个 thenable 对象 thenable 对象指的是具有 then 方法的对象,比如下面这个对象。 var thenable = { then: function (resolve, reject) { resolve(42); } }; Promise.resolve 方法会将这个对象转为 Promise 对象,然后就立即执行 thenable 对象的 then 方法。 var thenable = { then: function (resolve, reject) { resolve(42); } }; var p1 = Promise.resolve(thenable); p1.then(function (value) { console.log(value); // 42 }); 上面代码中,thenable 对象的 then 方法执行后,对象 p1 的状态就变为 resolved,从而立即执行最后那个 then 方法指定的回调函数,输出 42。 (3)参数不是具有 then 方法的对象,或根本就不是对象 如果参数是一个原始值,或者是一个不具有 then 方法的对象,则 Promise.resolve 方法返回一个新的 Promise 对象,状态为 resolved。 var p = Promise.resolve('Hello'); p.then(function (s) { console.log(s) }); // 'Hello' var p1 = Promise.resolve(true); p1.then(function (b) { console.log(b) }); // true var p2 = Promise.resolve(1); p1.then(function (n) { console.log(n) }); // 1 (4)不带有任何参数 Promise.resolve 方法允许调用时不带参数,直接返回一个 resolved 状态的 Promise 对象。 所以,如果希望得到一个 Promise 对象,比较方便的方法就是直接调用 Promise.resolve 方法。 Promise.reject() Promise.reject 方法也会返回一个新的 Promise 实例,该实例的状态为 rejected。 注意,Promise.reject 方法的参数,会原封不动地作为 reject 的参数,变成后续方法的参数。这一点与 Promise.resolve 方法不一致。 var thenable = { then(resolve, reject) { reject('出错了'); } }; Promise.reject(thenable) .catch(e = > { console.log(e === thenable) }) // true 上面代码中,Promise.reject 方法的参数是一个 thenable 对象,执行以后,后面 catch 方法的参数不是 reject 抛出的 出错了 这个字符串,而是 thenable 对象。 加载图片 我们可以将图片的加载写成一个 Promise,一旦加载完成,Promise 的状态就发生变化。 function (path) { return new Promise(function (resolve, reject) { const image = new Image(); image.onload = resolve; image.onerror = reject; image.src = path; }); }; 封装ajax 我们可以将 ajax 请求写成一个 Promise,根据请求的不同状态改变 Promise 的状态。 function ajax(method, url, data) { var request = new XMLHttpRequest(); return new Promise(function (resolve, reject) { request.onreadystatechange = function () { if (request.readyState === 4) { if (request.status === 200) { resolve(request.responseText); } else { reject(request.status); } //欢迎加入全栈开发交流圈一起学习交流:864305860 } //面向1-3年前端人员 }; //帮助突破技术瓶颈,提升思维能力 request.open(method, url); request.send(data); }); } 总结 优点: 可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数(回调地狱)。 在异步执行的流程中,可以把执行代码和处理结果的代码清晰地分离开来。 缺点: 无法取消 Promise,一旦新建它就会立即执行,无法中途取消。 如果不设置回调函数,Promise 内部抛出的错误,不会反应到外部。 当处于 pending 状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

优秀的个人博客,低调大师

JavaScript—Chrome 调试(22)

本文包括浏览器调试,不包括web移动端调试。本文调试均在chrome浏览器进行 alert这个不用多说了,不言自明 console基本输出想必大家都在用console.log在控制台输出点东西,其实console还有其它的方法: console.log("打印字符串");//在控制台打印自定义字符串 console.error("我是个错误");//在控制台打印自定义错误信息 console.info("我是个信息");//在控制台打印自定义信息 console.warn("我是个警告");//在控制台打印自定义警告信息 console.debug("我是个调试");//在控制台打印自定义调试信息 cosole.clear();//清空控制台(这个下方截图中没有) 注意上面输出的error和throw出的error不一样,前者只是输出错误信息,无法捕获,不会冒泡,更不会中止程序运行。 格式化输出除此以外,console还支持自定义样式和类似c语言的printf形式 console.log("%s年",2016);//%s表示字符串 console.log("%d年%d月",2016,11);//%d表示整数 console.log("%f",3.1415926);//%f小数 console.log("%o",console);//%o表示对象 console.log("%c自定义样式","font-size:30px;color:#00f"); console.log("%c我是%c自定义样式","font-size:20px;color:green","font-size:10px;color:red"); <todo> DOM输出下面几个比较简单的,就不举例子了,简单说一下: var ul = document.getElementsByTagName("ul"); console.dirxml(ul); //树形输出table节点,即<table>和它的innerHTML,由于document.getElementsByTagName是动态的,所以这个得到的结果肯定是动态的 对象输出 var o = { name:"Lily", age: 18 }; console.dir(obj);//显示对象自有属性和方法 对于多个对象的集合,你可以这样,输出更清晰: var stu = [{name:"Bob",age:13,hobby:"playing"},{name:"Lucy",age:14,hobby:"reading"},{name:"Jane",age:11,hobby:"shopping"}]; console.log(stu); console.table(stu); 成组输出 //建立一个参数组 console.group("start"); //引号里是组名,自己起 console.log("sub1"); console.log("sub1"); console.log("sub1"); console.groupEnd("end"); 函数计数和跟踪 function fib(n){ //输出前n个斐波那契数列值 if(n == 0) return; console.count("调用次数");//放在函数里,每当这句代码运行输出所在函数执行次数 console.trace();//显示函数调用轨迹(访问调用栈) var a = arguments[1] || 1; var b = arguments[2] || 1; console.log("fib=" + a); [a, b] = [b, a + b]; fib(--n, a, b); } fib(6); 注:Chrome开发者工具中的Sources标签页也在Watch表达式下面显示调用栈。 计时 console.time() //计时开始 fib(100); //用上述函数计算100个斐波那契数 console.timeEnd() //计时结束并输出时长 断言语句,这个c++调试里面也经常用到。js中,当第一个表达式或参数为true时候什么也不发生,为false时终止程序并报错 console.assert(true, "我错了"); console.assert(false, "我真的错了"); 性能分析 function F(){ var i = 0; function f(){ while(i++ == 1000); } function g(){ while(i++ == 100000); } f(); g(); } console.profile(); F(); console.profileEnd(); 注:Chrome开发者工具中的Audits标签页也可以实现性能分析。 debugger这个重量级的是博主最常用的,可能是c++出身,对于单步调试由衷的热爱。单步调试就是点一下,执行一句程序,并且可以查看当前作用域可见的所有变量和值。而debugger就是告诉程序在那里停下来进行单步调试,俗称断点。右边按钮如下: Pause/Resume script execution:暂停/恢复脚本执行(程序执行到下一断点停止)。Step over next function call:执行到下一步的函数调用(跳到下一行)。Step into next function call:进入当前函数。Step out of current function:跳出当前执行函数。Deactive/Active all breakpoints:关闭/开启所有断点(不会取消)。Pause on exceptions:异常情况自动断点设置。其实右侧还有很多强大的功能 Watch:Watch表达式Call Stack: 栈中变量的调用,这里是递归调用,肯定是在内存栈部分调用。Scope:当前作用域变量观察。BreakPoints:当前断点变量观察。XHR BreakPoints:面向Ajax,专为异步而生的断点调试功能。DOM BreakPoints:主要包括下列DOM断点,注册方式见下图当节点属性发生变化时断点(Break on attributes modifications)当节点内部子节点变化时断点(Break on subtree modifications)当节点被移除时断点(Break on node removal) Global Listeners:全局事件监听 Event Listener Breakpoints:事件监听器断点,列出了所有页面及脚本事件,包括:鼠标、键盘、动画、定时器、XHR等等。 chrome中的调试技巧 DOM元素的控制台书签 Chrome开发者工具和Firebug都提供了书签功能,用于显示你在元素标签页(Chrome)或HTML标签页(Firebug)中最后点击的DOM元素。如果你依次选择了A元素、B元素和C元素,那么&dollar;0 表示C元素,&dollar;1 表示B元素,&dollar;2 表示A元素。(这个和正则表达式的&dollar;符号类似,不过顺序不同) 如果你想调试f函数,用debug(f)语句可以增加这种断点。 Sources标签页左侧面板上有一个代码片段(Snippet)子标签页,可用于保存代码片段,帮你调试代码。 可以用Chrome开发者工具Sources标签页中的格式化按钮(Pretty Print Button)格式化压缩后的代码。 在Network面板,选择一个资源文件,右键Copy Response可快速复制响应内容。 利用媒体查询,这个主要是在Device Mode调节不同的分辨率显示。 选择Elements,按 Esc > Emulation > Sensors进行传感器模拟。 点击渐入效果样式图标(紫色图标),可以预览动画效果,并可对相应的贝塞尔曲线(cubic-bezier)进行调节动画效果。 在Source中按住Alt键并拖动鼠标进行多列内容选择。 Elements面板右键执行DOM元素节点,选择Force Element State或者点击右侧Toggle Element State图标可以出发伪类。 Network面板中选择一张图片,在右侧图片上鼠标右键选择copy it as a Data URI,就可以获取图片的Data URL (base64编码)。 通过按住Ctrl键可以添加多个编辑光标,同时对多处进行编辑。按下Ctrl + U可以撤销编辑。 Elements面板右侧的Style编辑器中,点击颜色十六进制编码前的小色块,会弹出一个调色板。 按下Alt键并且鼠标双击选择DOM元素前面的箭头,就会展开该DOM元素下的所有字节点元素. 快捷键: 快速定位到行:快捷键Ctrl+O(Mac:CMD+O),输入:行号:列号 来进行定位元素搜索:快捷键Ctrl+F(Mac:CMD+F),试试在搜索栏输入ID选择符或者类选择符就可以定位到元素啦 调试过程注意事项 1.避免记录引用类型当记录对象或数组时,永远记得你在记录什么。记录原始类型时,使用带断点的watch表达式。如果是异步代码,避免记录引用类型。 var arr = [{ num: 0 }]; setInterval(function(){ console.log(arr); arr[0].num += 1; }, 1000); 这里,第一个属性中对象引用的值是不可靠的。当你第一次在开发者工具中显示这个属性时,num的值就已经确定了。之后无论你对同一个引用重新打开多少次都不会变化。 2.尽可能使用 source map。有时生产代码不能使用source map,但不管怎样,你都不应该直接对生产代码进行调试。 这里推荐一下我的前端学习交流群:731771211,里面都是学习前端的,群里会不定期更新最新的教程和学习方法,有想学习web前端的,或是转行,或是大学生,还有工作中想提升自己能力的web前端党欢迎加入。

优秀的个人博客,低调大师

JavaScript—获取参数(23)

1.隐式创建 html 标签 <input type="hidden" name="tc_id" value="{{tc_id}}"> 这种方法一般配合ajax,上面的value使用了模板引擎2.window['data'] window['name'] = "the window object"; 3.使用localStorage,cookie等存储 window.localStorage.setItem("name", "xiaoyueyue"); window.localStorage.getItem("name") 特点:cookie,localStorage,sessionStorage,indexDB 从上表可以看到,cookie 已经不建议用于存储。如果没有大量数据存储需求的话,可以使用 localStorage 和 sessionStorage 。对于不怎么改变的数据尽量使用 localStorage 存储,否则可以用 sessionStorage 存储。 注意点:存储 object类型数据,此深拷贝方法会忽略掉函数和 undefined var obj = { type: undefined, text: 'xiaoyueyue', methord: function () { alert("I am an methord") } } localStorage.setItem('data', JSON.stringify(obj)); console.log(JSON.parse(localStorage.getItem('data'))); // {text: "xiaoyueyue"} 4.获取地址栏方法自己封装的方法 function parseParam(url) { var paramArr = decodeURI(url).split("?")[1].split("&"), obj = {}; for (var i = 0; i < paramArr.length; i++) { var item = paramArr[i]; if (item.indexOf("=") != -1) { var tmp = item.split("="); obj[tmp[0]] = tmp[1]; } else { obj[item] = true; } } return obj; } 2.正则表达式方法 function GetQueryString(name) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var r = window.location.search.substr(1).match(reg); if (r != null) return unescape(r[2]); return null; } 5.标签绑定函数传参 <!--base--> <button id="test1" onclick="alert(id)">test1</button> <!--高级--> <button id="test" name="123" yue="xiaoyueyue" friend="heizi" onclick="console.log(this.getAttribute('yue'),this.getAttribute('friend'))">test</button> this拓展使用this传参,在使用art-template中琢磨出来的,再也不用只传递一个id拼接成好几个参数了!happy! var box = document.createElement("div"); box.innerHTML = "<button id='1' data-name='xiaoyueyue' data-age='25' data-friend='heizi' onclick='alertInfo(this.dataset)'>点击</button>"; document.body.appendChild(box); // name,age,friend function alertInfo(data) { alert('大家好,我是' + data.name + ', 我今年' + data.age + '岁了,我的好朋友是' + data.friend + ' !') } 这里需要注意一点:存储的data—含有大写的单词 =》这里会统一转化为小写,比如:data-orderId = “2a34fb64a13211e8a0f00050568b2fdd”,在实际取值的时候为 this.dataset.orderid; event既然可以使用this,那么在事件当中event.target方法也是可以的: 根据 class 获取当前的索引值,参数可以为 event对象 var getIndexByClass = function (param) { var element = param.classname ? param : param.target; var className = element.classname; var domArr = Array.prototype.slice.call(document.querySelectorAll('.' + className)); for (var index = 0; index < domArr.length; index++) { if (domArr[index] === element) { return index; } } return -1; }, 6.HTML5 data-* 自定义属性 <button data-name="xiaoyueyue">点击</button> var btn = document.querySelector("button") btn.onclick = function () { alert(this.dataset.name) } 7.字符串传参单个参数 var name = 'xiaoyueyue', age = 25; var box = document.createElement("div"); box.innerHTML = '<button onclick="alertInfo(\'' + name + '\')">点击</button>'; document.body.appendChild(box); // name, age function alertInfo(name, age, home, friend) { alert("我是" + name) } 多参传递 var name = 'xiaoyueyue', age = '25', home = 'shanxi', friend = 'heizi', DQ = "&quot;"; // 双引号的超文本标记语言 var params = "&quot;" + name + "&quot;,&quot;" + age + "&quot;,&quot;" + home + "&quot;,&quot;" + friend + "&quot;"; var params2 = DQ + name + DQ + ',' + DQ + age + DQ + ',' + DQ + home + DQ + ',' + DQ + friend + DQ; var box = document.createElement("div"); box.innerHTML = "<button onclick='alertInfo(" + params + ")'>点击</button>"; console.log(box) document.body.appendChild(box); // name, age,home,friend function alertInfo(name, age, home, friend) { alert("我是" + name + ',' + "我今年" + age + "岁了!") 复杂传参 var data = [ { "name": "xiaoyueyue", "age": "25", "home": "shanxi", "friend": "heizi" } ] var box = document.createElement("div"),html =''; for (var i = 0; i < data.length; i++) { html += "<button id='btn' onclick='alertInfo(id,\"" + data[i].name + "\",\"" + data[i].age + "\",\"" + data[i].home + "\",\"" + data[i].friend + "\")'>点击</button>"; } box.innerHTML = html; document.body.appendChild(box); function alertInfo(id, name, age, home, friend) { alert("我是 " + name + " , " + friend + " 是我的好朋友") } 8.argumentsarguments对象是所有(非箭头)函数中都可用的局部变量。你可以使用arguments对象在函数中引用函数的参数。它是一个类数组的对象。 <button onclick="fenpei('f233c7a290ae11e8a0f00050568b2fdd','100','0号 车用柴油(Ⅴ)')">分配</button> function fenpei() { var args = Array.prototype.slice.call(arguments); alert("我是" + args[2] + "油品,数量为 " + args[1] + " 吨, id为 " + args[0]) } 9.form表单借助form表单,ajax传递序列化参数 // form表单序列化,摘自JS高程 function serialize(form) { var parts = [], field = null, i, len, j, optLen, option, optValue; for (i = 0, len = form.elements.length; i < len; i++) { field = form.elements[i]; switch (field.type) { case "select-one": case "select-multiple": if (field.name.length) { for (j = 0, optLen = field.options.length; j < optLen; j++) { option = field.options[j]; if (option.selected) { optValue = ""; if (option.hasAttribute) { optValue = (option.hasAttribute("value") ? option.value : option.text); } else { optValue = (option.attributes["value"].specified ? option.value : option.text); } parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(optValue)); } } } break; case undefined: //fieldset case "file": //file input case "submit": //submit button case "reset": //reset button case "button": //custom button break; case "radio": //radio button case "checkbox": //checkbox if (!field.checked) { break; } /* falls through */ default: //don't include form fields without names if (field.name.length) { parts.push(encodeURIComponent(field.name) + "=" + encodeURIComponent(field.value)); } } } return parts.join("&"); } 列子: <form id="formData"> <div class="pop-info"> <label for="ordersaleCode">订单编号:</label> <input type="text" id="ordersaleCode" name="ordersaleCode" placeholder="请输入订单编号" /> </div> <div class="pop-info"> <label for="extractType">配送方式:</label> <select id="extractType" name="extractType" class="mySelect"> <option value="0" selected>配送</option> <option value="1">自提</option> </select> </div> </form> <button>获取参数</button> document.querySelector("button").onclick = function () { console.log('param: '+serialize(document.getElementById("formData"))); // param: ordersaleCode=&extractType=0 }

优秀的个人博客,低调大师

JavaScript基本语法(三)

数组 一.数组的概念 二.数组的定义 三.名词解释 四.获取数组元素 五.数组的赋值 六.遍历数组 七.冒泡排序 数组 一、数组的概念: 所谓数组,就是将多个元素(通常是同一类型)按一定顺序排列放到一个集合中,那么这个集合我们就称之为数组。 二、数组的定义 方式一:通过构造函数的方式定义一个数组 var 数组名= new array(); var arr = new array();//空数组 方式二:通过字面量的方式创建数组 var 数组名= []; var arr = [];//空数组 三、名词解释 1、数组元素:数组中存储的每个数据,都是数组的元素。 例子 var arr= [10,20,30]; //这里的10、20、30就是数组的元素 2、数组长度:就是数组的元素的个数。 例子 var arr= [10,20,30]; //这个数组的长度就是3 3、数组索引(下标):用来存储或者访问数组中的数据的,索引从0开始,到长度减1结束。 例子 var arr= [10,20,30]; arr[0]=100;//设置数组中某个位置的值 //中括号里的0就是数组的索引 四、获取数组元素 格式:数组名[索引] 例子: var arr= [10,20,30]; console.log(arr[0]);//10 console.log(arr[1]);//20 console.log(arr[2]);//30 console.log(arr[2]);//undefined 五、数组的赋值 格式:数组名[下标/索引]=值; 如果下标有对应的值,会把原来的值覆盖,如果下标不存在,会给数组新增一个元素。 例子: var arr= [10,20,30]; arr[0]=100; arr[3]=50; console.log(arr[0]);//100 console.log(arr[3]);//50 六.遍历数组 遍历:遍及所有,对数组的每一个元素都访问一次就叫遍历。 //语法 for(var i = 0; i < arr.length; i++) { } 例子 var arr=[10,20,30,40]; for (var i=0;i<arr.length;i++) { console.log(arr[i]); } 七、冒泡排序 概念:把所有的数据按照一定的顺序排序 降序 var arr = [3,5,77,9,10,32,45,64,2]; for (var i=0;i<arr.length-1;i++) { for (var j=0;j<arr.length-1-i;j++) { if(arr[j]<arr[j+1]){ var temp=arr[j]; arr[j]=arr[j+1]; arr[j+1]=temp; } } } console.log(arr);

优秀的个人博客,低调大师

JavaScript基本语法(二)

分支结构 1.if语句 2.if-else语句 3.三元表达式 4.if-else if-else if语句 5.switch-case 6.总结 循环结构 1.while循环 2.do-while循环 3.for循环 if语句 基本语法: if(表达式){ 代码 } 执行过程: 先判断表达式的结果是true还是false,如果是true则执行代码,如果是false,则不执行。 例子: 判断年龄是否大于等于18岁,如果大于18岁则可以看电影了。 var age = 19; if(age>=18){ console.log("可以看电影了"); } if-else语句 基本语法: if(表达式){ 代码1 }else{ 代码2 } 执行过程: 如果表达式的结果为true则执行代码1,如果表达式的结果是false,则执行代码2. 例子:小明的年龄是否是成年人,如果是成年人则提示“可以看电影了”,否则提示“回家写作业”。 var age = 10; if(age>=18){ console.log(“可以看电影了”); }else{ console.log("回家写作业"); } 三元表达式 基本语法: var变量 = 表达式1 ?表达式2:表达式3; 执行过程: 判断表达式1的结果是true还是false,如果是true则执行表达式2,然后把结果给变量;如果表达式1的结果是false,则执行表达式3,把结果给变量。 例子:判断是成年还是未成年 var age = 20; var result = age>=18?"成年了":"未成年"; console.log(result); if-else if-else if语句 基本语法: if(表达式1){ 代码1 }else if(表达式2){ 代码2 }else{ 代码3 } 执行过程: 先判断表达式1,如果结果为true执行代码1,如果为false,则判断表达式2,表达式2结果为true则执行代码2,如果为false则执行代码3. 例子: 成绩的结果是90到100(包含)之间则显示“A级” 成绩的结果是80到90(包含)之间则显示“B级” 成绩的结果是70到80(包含)之间则显示“C级” 成绩的结果是60(包含)到70(包含)之间则显示“D级” 成绩的结果是0到60(不包含)之间则显示“E级” var score = 78; if(score>90&&score<=100){ console.log("A级"); }else if(score>80){ console.log("B级"); }else if(score>70){ console.log("C级"); }else if(score>=60){ console.log("D级"); }else{ console.log("E级"); } switch-case 基本语法: switch(表达式){ case值1: 代码1; break; case值2: 代码2; break; case值3: 代码3; break; ...多个case default: 代码4; break; } 执行过程: 获取表达式的值,和值1比较,如果一样,则执行代码1,遇到break则跳出整个语句,后面的代码不执行。 如果表达式的值和1不一样,则和值2比较,如果相同则执行代码2,遇到break则跳出。 如果表达式的值和2不一样,则和值3比较,如果相同则执行代码3,遇到break则跳出。都不同则执行代码4 例子: 或许一个人成绩的级别 如果是A级则显示“90到100”之间的数 如果是B级则显示“80到90”之间的数 如果是C级则显示“70到80”之间的数 如果是D级则显示“60到70”之间的数 否则显示“0到59”之间的数 var level = "C" switch(level){ case"A": console.log("90到100"); break; case"B": console.log("80到90"); break; case"C": console.log("70到80"); break; case"D": console.log("60到70"); break; default: console.log("0到59"); break; } 总结 1.if语句:一个分支 2.if-else语句:两个分支,最后只执行一个 3.三元表达式:和if-else语句是一样的 4.if-else if-else if语句:多个分支,最终执行一个 5.switch-case:多分支语句,最终也会执行一个 如果有多个分支,是针对范围的判断一般选择if-else if语句 如果有多个分支,是针对具体的值判断,一般选用switch-case while循环 基本语法: var 变量 = 0;//计数器 while(循环条件){ 循环体; 计数器++; } 执行过程: 先判断循环条件是否成立,如果是false,那么循环的代码(while大括号中的代码都不执行),如果是true,那么先执行循环体,然后执行计数器,然后跳到循环条件,再次判断是否成立,一直如此。 例子: 计算1-100之间所有数字的和 var sum = 0; //存储最终的和 var i =1; //计数器 while(i<=100){ sum=sum+I; I++; } console.log(sum); // 5050 do-while循环 基本语法: do{ 循环体; }while(循环条件); 执行过程: 先执行一次循环体,然后判断条件是否成立,不成立则跳出循环,成立则执行循环体,然后再判断条件是否成立,成立则继续循环,否则跳出。 例子: 输出十次“你好” var j = 0; do{ console.log("你好"); j++; }while(j<10); for循环 基本语法: for(表达式1;表达式2;表达式3;){ 循环体; } 执行过程: 先执行一次表达式1,然后判断表达式2,如果不成立则直接跳出循环,如果表达式2成立,执行循环体的代码,结束后跳到表达式3执行,然后跳到表达式2,判断表达式2是否成立,不成立则跳出循环,如果表达式2成立,则执行循环体,然后再跳到表达式3,再跳表达式2,判断是否成立,一直如此。 例子: 求1-100之间所有数字的和 var sum = 0; for(var j=1;j<=100;j++){ sum = sum+j; } console.log(sum);

优秀的个人博客,低调大师

JavaScript常用设计模式

设计模式 设计模式是一种在长时间的经验与错误中总结出来可服用的解决方案。 设计模式主要分为3类: 创建型设计模式:专注于处理对象的创建 Constructor构造器模式,Factory工厂模式,Singleton单例模式,builder生成器模式 结构型设计模式:对象间组合,建立对象之间的关系 Decorator装饰者模式,Facade外观模式,Flyweight享元模式,Adapter适配器模式,Proxy代理模式 行为设计模式:简化和改善对象间的通信 Mediator中介者模式,Observer观察者模式 常用的设计模式 1. 观察者模式 一个目标对象维持着一系列依赖于它的对象,将有关状态的任何变更自动通知观察者们。在观察者模式中,观察者需要直接订阅目标对象,观察者与目标对象之间有一定的依赖关系。 有4个重要的概念 目标对象(被观察者):维护一组观察患者,提供管理观察者的方法。 观察者: 提供一个更新接口,用于收到通知时,进行更新 具体目标对象:代表具体的目标对象 具体观察者:代表具体的观察者 // 目标对象 class Subject { constructor() { // 观察者列表 this.observers = [] } addObserver(observer) { this.observers.push(observer) } removeObserver() { this.observers.pop() } notify() { this.observers.forEach(observer => { observer.update() }) } } // 观察者 class Observer { constructor() { // 使用时会被具体update方法覆盖 this.update = function () { // .. } } } // 具体目标对象 class currentSubject extends Subject { constructor() { super() } // 其他自定义方法 dosomething() { console.log('currentSubject change') this.notify() } } // 具体观察者 class currentObserver extends Observer { constructor() { super() } // 重写update update() { console.log('change!') } } // 订阅 let curSubject = new currentSubject() let curObserver = new currentObserver() curSubject.addObserver(curObserver) // 触发 curSubject.dosomething() // currentSubject change 2.发布/订阅模式 发布订阅模式可以说是观察这模式的一种变体,一种实现。它使用一个主题/事件通道,介于发布者和订阅者之间,避免了发布者和订阅者之间的依赖关系。 class PubSub { constructor() { // 主题/事件通道 this.topics = {} } publish(topic, args) { if (!this.topics[topic]) { return } let subscribers = this.topics[topic] subscribers.forEach(subscriber => { subscriber.updata(args) }) } subscribe(topic, subscriber ) { if (!this.topics[topic]) { this.topics[topic] = [] } this.topics[topic].push(subscriber ) } } let pubsub = new PubSub() pubsub.subscribe('one', subscriber ) pubsub.publish('one', 'some args') 3. 工厂模式 工厂函数提供一个通用的接口来创建对象,我们可以指定我们希望创建的对象类型,我们通知工厂函数需要什么类型的对象并提供对应的数据,返回对应的实例。 class Car { constructor(options) { this.doors = options.doors || 4; this.state = options.state || "brand new"; this.color = options.color || "silver"; } } class Truck { constructor(options) { this.state = options.state || "used"; this.wheelSize = options.wheelSize || "large"; this.color = options.color || "blue"; } } function vehicleFactory (options) { if (options.type === 'car') { return new Car(options) } else { return new Truck(options) } } 何时使用工厂模式 当我们的对象比较复杂的时候。 当我们需要根据不同情况创建不同对象实例的时候。 当我们需要创建许多相似对象的时候。 缺点 使用不当会增加程序的复杂度 4. 抽象工厂模式 抽象工厂模式,将对象的实现细节抽离出来。适用于需要和多种对象一起工作的场景。 class Truck { constructor(options) { this.state = options.state || "used"; this.wheelSize = options.wheelSize || "large"; this.color = options.color || "blue"; } } class Car { constructor(options) { this.doors = options.doors || 4; this.state = options.state || "brand new"; this.color = options.color || "silver"; } } class AbstractFactory { constructor() { this.types = {} } registerFactory(type, factory) { this.types[type] = factory } getInstance(type, args) { let factory = this.types[type] if (factory) { return new factory(args) } } } let abstractFactory = new AbortController() abstractFactory.registerFactory('car', Car) abstractFactory.registerFactory('truck', Truck) abstractFactory.getInstance('car', options) abstractFactory.getInstance('truck', options) 5. 单例模式 单例模式限制一个类只有一个实例化对象。 class Obj(data) { // .... } // 利用闭包实现单例模式,确保obj类只有一个实例 function singleton (data) { var instance; return function () { if (!instance) { instance = new Obj(data) } return instance } } 6. 中介者模式 中介者模式就是提供一个中心点给系统不同组件之间进行通信,降低系统组件之间的耦合程度。 // 实现与发布/订阅模式类似 观察者模式和发布订阅模式专注于维护目标对象和观察者之间的关系,当主题对象发送变化时,通知所有对改主题感兴趣的观察者。而中介者模式的话,专注于限制对象的通信必须通过中介者来通信。两者都提倡松耦合。 7. 装饰者模式 装饰者模式,通过一个装饰类对现有动态添加行为,以及对原有行为进行装饰。 // o为已有对象 var M20 = function(o){ // 这里定义一个装饰类 var str = '20多岁的时候,'; // o是传入的对象,调用传入对象的方法,加以装饰 this.eat = function(){ return str + o.eat()+",肥得很!"; }; this.drink = function(){ return str + o.drink()+",就是个水桶!"; }; this.coding = function(){ return str + o.coding()+",代码又写得撇!"; }; } alert(new M20(david).eat()); // 20多岁的时候,大卫是个大胖子,一天只晓得吃,肥得很! alert(new M20(david).drink()); // 20多岁的时候,大卫除了吃就是喝,就是个水桶! alert(new M20(david).coding()); // 20多岁的时候,写代码吧,大卫,代码又写得撇! 8. 适配器模式 使用一个新的接口对现有的接口进行包装,处理数据与接口的不匹配。 function api (x1, x2, x3) { console.log(x1 + x2 + x3); // 用console.log来模拟接口的相关操作 } var data = { a: '我', b: '很', c: '帅' } function adapterApi (o) { // 通过适配器函数来调用目的api api(o.a, o.b, o.c); } adapterApi(data); // 我很帅 原文发布时间为:2018年07月02日原文作者:掘金本文来源:掘金如需转载请联系原作者

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Rocky Linux

Rocky Linux

Rocky Linux(中文名:洛基)是由Gregory Kurtzer于2020年12月发起的企业级Linux发行版,作为CentOS稳定版停止维护后与RHEL(Red Hat Enterprise Linux)完全兼容的开源替代方案,由社区拥有并管理,支持x86_64、aarch64等架构。其通过重新编译RHEL源代码提供长期稳定性,采用模块化包装和SELinux安全架构,默认包含GNOME桌面环境及XFS文件系统,支持十年生命周期更新。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册