-
Notifications
You must be signed in to change notification settings - Fork 0
/
content.json
1 lines (1 loc) · 68.5 KB
/
content.json
1
{"meta":{"title":"chochi's workshop","subtitle":null,"description":null,"author":"chochi","url":"http://yoursite.com","root":"/"},"pages":[],"posts":[{"title":"原生js实现精确倒计时","slug":"004原生js实现精确倒计时","date":"2019-05-30T13:29:59.432Z","updated":"2019-06-11T07:26:35.281Z","comments":true,"path":"2019/05/30/004原生js实现精确倒计时/","link":"","permalink":"http://yoursite.com/2019/05/30/004原生js实现精确倒计时/","excerpt":"原生js实现精确倒计时实现查了一堆资料,发现前端是无法实现精确倒计时的哈哈哈哈哈哈哈哈哈哈!顶多用本机时间相减。","text":"原生js实现精确倒计时实现查了一堆资料,发现前端是无法实现精确倒计时的哈哈哈哈哈哈哈哈哈哈!顶多用本机时间相减。 实现的一个简易CountDownTimer 问题看了很多,基本都是用 setInterval做的,但是该函数是异步的,要等待同步操作做完才开始处理。假设,倒计时页面有很多同步工作占用了很多时间,那么用户点击下开始倒计时的按钮会出现一段无法预料的等待时间。。是不是这样我再摸索一下。","categories":[{"name":"js","slug":"js","permalink":"http://yoursite.com/categories/js/"},{"name":"demo","slug":"js/demo","permalink":"http://yoursite.com/categories/js/demo/"}],"tags":[],"author":"chochi"},{"title":"定位、浮动 布局","slug":"003定位浮动布局","date":"2019-05-29T13:55:40.442Z","updated":"2019-06-11T07:26:20.594Z","comments":true,"path":"2019/05/29/003定位浮动布局/","link":"","permalink":"http://yoursite.com/2019/05/29/003定位浮动布局/","excerpt":"1 position position 的可选值有四个:static、relative、absolute、fixed,tricky 是被定位的元素层次(z-index)会得到提高 元素脱离文档流后不会撑开父元素高度","text":"1 position position 的可选值有四个:static、relative、absolute、fixed,tricky 是被定位的元素层次(z-index)会得到提高 元素脱离文档流后不会撑开父元素高度 1.1 static 如果元素 position 属性值为 static(或者未设 position 属性),该元素出现在正常的流中(忽略 top, bottom, left, right 或者 z-index 声明)。 1.2 relative 首先按默认方式(static)生成一个元素。 然后相对于static生成的位置位置移动,移动的方向和幅度由 left、right、top、bottom 属性确定,其他的元素的位置则不会受该元素的影响发生位置改变来弥补它偏离后剩下的空隙(即保持文档流)。 1.3 absolute 绝对定位的元素使用 left、right、top、bottom 属性相对于其最接近的一个具有定位属性的父元素祖先类的 border 进行绝对定位。 如果不存在这样的父元素,则相对于 html元素,即相对于浏览器窗口。 脱离标准文档流。 Note : 绝对(absolute)定位对象在可视区域之外会导致滚动条出现。而放置相对(relative)定位对象在可视区域之外,滚动条不会出现。 relative和static方式在最外层时是以< body> 标签为定位原点的,而absoulte方式在无父级是position非static定位时是以 html 作为原点定位。 1.3 fixed fixed 生成绝对定位的元素,该元素相对于浏览器窗口进行定位。 固定定位的元素不会随浏览器窗口的滚动条滚动而变化,也不会受文档流动影响,而是始终位于浏览器窗口内视图的某个位置。 一个固定定位元素不会保留它原本在页面应有的空隙(脱离文档流) 2 float2.1 使用 float 置了float属性的元素会从普通文档流中脱离,相当于不占据任何空间。 让block元素无视float元素,让inline元素像流水一样围绕着float元素实现浮动布局。 父元素高度塌陷问题,子元素为浮动,则脱离了文档流,父元素不会把该元素在包括在边界内。(解决:在父元素内部末尾添加一个块级元素 or 使父元素成为BFC) 一旦元素float的属性不为none,则其display计算值就是block或者table。块状化意思是可以像block元素一样设置宽和高,并不是真正的块元素。 2.2 清除float1 使用 clear 规定元素的哪一侧不允许其他浮动元素。1clear: none | left | right | both none:默认值,允许两边都有浮动对象; left:不允许左侧有浮动对象; right:不允许右侧有浮动对象; both:两侧不允许有浮动对象。 2 利用伪元素12345<div class=\"topDiv clearfix\"> <div class=\"textDiv\">...</div> <div class=\"floatDiv\">float left</div></div><div class=\"bottomDiv\">...</div> 123456.clearfix:after { content: ''; height: 0; display: block;// or table clear: both;} 2 BFC 块级格式化上下文将父元素设定为BFC可以消除浮动带来的影响 块级格式化上下文是CSS可视化渲染的一部分。是一个独立的渲染区域,只有block-level box参与,规定了内部block-level box的渲染方式,以及浮动相互之间的影响关系。 BFC有自己的一套内部子元素渲染的规则,不影响外部渲染,也不受外部渲染影响。 BFC的区域不会和外部浮动盒子的外边距区域发生叠加(故BFC的区域不会与float的元素区域重叠)。但BFC内部的margin会发生重叠。 BFC在计算高度的时候,内部浮动元素的高度也要计算在内(而position为absolute的元素可以超出它的包含块边界) 以下声明都可以创建BFC 根元素 float的值不为none; overflow的值不为visible; display的值为inline-block、table-cell、table-caption(table会默认生成一个匿名的table-cell也可以生成BFC); position的值为absolute或fixed; 资料引用 定位属性position使用详解 学习CSS布局 CSS深入理解值float浮动 清除浮动的四种方式及其原理理解","categories":[{"name":"CSS","slug":"CSS","permalink":"http://yoursite.com/categories/CSS/"},{"name":"布局","slug":"CSS/布局","permalink":"http://yoursite.com/categories/CSS/布局/"}],"tags":[],"author":"chochi"},{"title":"ECMA6 Promise对象","slug":"003ECMA6-Promise对象","date":"2019-05-28T08:26:49.783Z","updated":"2019-06-11T07:26:13.115Z","comments":true,"path":"2019/05/28/003ECMA6-Promise对象/","link":"","permalink":"http://yoursite.com/2019/05/28/003ECMA6-Promise对象/","excerpt":"1 概述 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。","text":"1 概述 所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。 1.1 Promise 对象特点 对象的状态不受外界影响。 Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。 一旦状态改变,就不会再变,任何时候都可以得到这个结果。 Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果,这时就称为 resolved(已定型)。(本章后面的resolved统一只指fulfilled状态,不包含rejected状态。) 无法取消Promise,一旦新建它就会立即执行(可以封装它调用执行),无法中途取消。 12345678910// 封装promise function getPromise(){ const promise = new Promise(function(resolve,reject){ console.log('promise is running'); resolve('some data'); reject('other data'); }); return promise; } getPromise()//promise is running 2 基本用法2.1 创建 Promise 对象 Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。它们是两个函数,由 JavaScript 引擎提供,不用自己部署。 123456789const promise = new Promise(function(resolve, reject) { // ... some code if (/* 异步操作成功 */){ resolve(value); // 将Promise对象状态更新 未完成 -> 成功 参数传给then调用的函数 } else { reject(error); // 更新 未完成 -> 失败 }}); Promise实例生成以后,可以用then方法分别指定resolved状态和rejected状态的回调函数。这两个函数都接受Promise对象传出的值作为参数。 12345678promise.then( function(value) { // success }, function(error) { // failure 可选 }); 2.2 执行顺序 Promise 新建后就会立即执行。 then方法指定的回调函数,将在当前脚本所有同步任务执行完才会执行 1234567891011121314let promise = new Promise(function(resolve, reject) { console.log('Promise'); resolve();});promise.then(function() { console.log('resolved.');});console.log('Hi!');// Promise// Hi!// resolved 2.3 example Promise + AJAX + JSON 123456789101112131415161718192021222324252627282930313233const contanier = document.getElementById('contanier');function onJSON(url){ // --- promise --- const promise = new Promise( (resolve,reject)=>{ // --- AJAX --- let xhr = new XMLHttpRequest(); xhr.open('GET',url); xhr.responseType='json'; xhr.send(); const handler = () =>{ // console.log(xhr.status,xhr.readyState); if( xhr.readyState !== 4)// 4: request finished and response is ready return; if ( (xhr.status >= 200 && xhr.status<300)|| xhr.status === 304 ){ console.log(xhr.response); resolve('done!'); } else reject('failed!'); } xhr.onreadystatechange = handler; // --- END OF AJAX --- } ); // --- end of promise --- return promise;}// access-control-allow-origin: *onJSON('https://learnwebcode.github.io/json-example/animals-1.json').then( (info)=>console.log(info), (info)=>console.log(info)); 3 方法3.1 实例方法 Promise.prototype.then() then方法设置回调函数。 Promise.prototype.catch() romise.prototype.catch方法是.then(null, rejection)或.then(undefined, rejection)的别名,用于指定发生错误时的回调函数。then方法指定的回调函数,如果运行中抛出错误,也会被catch方法捕获。如果没有使用catch方法指定错误处理的回调函数,Promise 对象抛出的错误不会传递到外层代码。 Promise.prototype.finally() 方法用于指定不管 Promise 对象最后状态如何,都会执行的操作。该方法是 ES2018 引入标准的。 finally方法的回调函数不接受任何参数,这意味着没有办法知道,前面的 Promise 状态到底是fulfilled还是rejected。这表明,finally方法里面的操作,应该是与状态无关的,不依赖于 Promise 的执行结果。 3.2 对象方法 Promise.all() 等待多个异步操作完成:只有这 6 个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。 12345678910// 生成一个Promise对象的数组const promises = [2, 3, 5, 7, 11, 13].map(function (id) { return getJSON('/post/' + id + \".json\");}); Promise.all(promises).then(function (posts) { // ...}).catch(function(reason){ // ...}); 如果作为参数的 Promise 实例,自己定义了catch方法,那么它一旦被rejected,并不会触发Promise.all()的catch方法。 123456789101112131415161718192021const p1 = new Promise((resolve, reject) => { resolve('hello');}) .then(result => result) .catch(e => e);const p2 = new Promise((resolve, reject) => { throw new Error('报错了');}) .then(result => result) .catch(e => e);//该方法返回的是一个新的 Promise 实例,p2指向的实际上是这个实例。//该实例执行完catch方法后,也会变成resolved,//导致Promise.all()方法参数里面的两个实例都会resolved,//因此会调用then方法指定的回调函数,而不会调用catch方法指定的回调函数。Promise.all([p1, p2]) .then(result => console.log(result)) .catch(e => console.log(e));// [\"hello\", Error: 报错了] Promise.race(): 最早执行完的异步操作返回的状态为最终状态。 Promise.resolve() 将现有对象转为 Promise 对象。 如果参数是 Promise 实例,原封不动地返回这个实例。 参数是一个 thenable 对象(thenable对象指的是具有then方法的对象),将这个对象转为 Promise 对象,然后就立即执行thenable对象的then方法。 参数不是具有then方法的对象,或根本就不是对象,则Promise.resolve方法返回一个新的 Promise 对象,状态为resolved。Promise.resolve方法的参数,会同时传给回调函数。 不带有任何参数,直接返回一个resolved状态的 Promise 对象。 Promise.reject() 返回一个新的 Promise 实例,该实例的状态为rejected。 Promise.try() 等待补充 资料引用 Promise 对象 大白话讲Promise1 判断图片加载完成","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"},{"name":"ECMA6","slug":"语言基础/ECMA6","permalink":"http://yoursite.com/categories/语言基础/ECMA6/"}],"tags":[{"name":"JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"React state更新","slug":"001react_state_update","date":"2019-05-26T13:39:00.347Z","updated":"2019-06-11T07:25:55.049Z","comments":true,"path":"2019/05/26/001react_state_update/","link":"","permalink":"http://yoursite.com/2019/05/26/001react_state_update/","excerpt":"1 state组件 私有组件 正确的修改方式是使用setState(),触发render函数刷新","text":"1 state组件 私有组件 正确的修改方式是使用setState(),触发render函数刷新 12// 正确this.setState({title: 'React'}); 2 state更新2.1 state 更新 setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。 setState 的批量更新优化也是建立在“异步”(合成事件、钩子函数)之上的,在原生事件和setTimeout 中不会批量更新,在“异步”中如果对同一个值进行多次 setState , setState 的批量更新策略会对其进行覆盖,取最后一次的执行,如果是同时 setState 多个不同的值,在更新时会对其进行合并批量更新。 React中会去维护一个标识(isBatchingUpdates),判断是直接更新还是先暂存state进队列。setTimeout以及原生事件都会直接去更新state,因此可以立即得到最新state。而合成事件和React生命周期函数中,是受React控制的,其会将isBatchingUpdates设置为 true,从而走的是类似异步的那一套。 setState真的是异步吗 2.2 state更新是一个浅合并的过程 当调用setState修改组件状态时,只需要传入发生改变的State,而不是组件完整的State,因为组件State的更新是一个浅合并(Shallow Merge)的过程。 2.3 demo 说明 | 个人理解有错就改! setState只是把要修改的状态放入一个队列中,React会优化真正的执行时机,并且React会出于性能原因,可能会将多次setState的状态修改合并成一次状态修改。 JS的顺序简单的来说可以划分执行顺序为 同步-> 异步->回调 123456789101112this.setState({ count: this.state.count + 1 }); // 异步1console.log(\"console: \" + this.state.count); // 同步1this.setState( { count: this.state.count + 1 },//异步2 () => {console.log(\"console from callback: \" + this.state.count); //回调1});this.setState( prevState => {console.log(\"console from func: \" + prevState.count); return {count: prevState.count + 1};},//异步3 ()=>{console.log('last console: '+ this.state.count)});// 回调2 所以执行顺序为: 同步1 : console: 0 异步1异步2合并为一次更新(demo是合并了,实际看render速度要不要合并),count=count+1=1 异步3,console from func: 1 count=precCount+1 =2 回调1,console from callback1 : 2 回调2, last console: 2 输出结果为: 1234console: 0 console from func: 1 console from callback: 2last console: 2 资料引用 深入理解React 组件状态(State) setState异步、同步与进阶","categories":[{"name":"框架","slug":"框架","permalink":"http://yoursite.com/categories/框架/"}],"tags":[{"name":"React","slug":"React","permalink":"http://yoursite.com/tags/React/"}]},{"title":"ECMA5 AJAX","slug":"10 Ajax","date":"2019-05-24T14:15:58.373Z","updated":"2019-05-24T14:28:33.806Z","comments":true,"path":"2019/05/24/10 Ajax/","link":"","permalink":"http://yoursite.com/2019/05/24/10 Ajax/","excerpt":"Ajax1 基础个人demo地址 1.1 概念 作用 Read data from a web server - after the page has loaded Update a web page without reloading the page Send data to a web server - in the background AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page.(异步刷新网页,不用整个网页渲染)","text":"Ajax1 基础个人demo地址 1.1 概念 作用 Read data from a web server - after the page has loaded Update a web page without reloading the page Send data to a web server - in the background AJAX allows web pages to be updated asynchronously by exchanging data with a web server behind the scenes. This means that it is possible to update parts of a web page, without reloading the whole page.(异步刷新网页,不用整个网页渲染) AJAX applications might use XML to transport data, but it is equally common to transport data as plain text or JSON text. 现在主流用 JSON 1.2 The XMLHttpRequest Object1.2.1 创建 | Chrome, Firefox, IE7+, Edge, Safari, Opera1var myRequest = new XMLHttpRequest(); 1.2.2 XMLHttpRequest Object Methods Method Description open(method, url, async, user, psw) Specifies the request method: the request type GET or POST url: the file location async: true (asynchronous) or false (synchronous) user: optional user name psw: optional password send() Sends the request to the server Used for GET requests send(string) Sends the request to the server. Used for POST requests true : 异步 execute other scripts while waiting for server response deal with the response after the response is ready 使用 onreadystatechange 事件(called every time the readyState changes)触发处理函数 false : 同步 其他模块会被block直到当前响应完成 无需使用 onreadystatechange 事件,直接编写处理函数 Synchronous XMLHttpRequest (async = false) is not recommended because the JavaScript will stop executing until the server response is ready. If the server is busy or slow, the application will hang or stop. 1.2.3 XMLHttpRequest Object Properties Property Description onreadystatechange Defines a function to be called when the readyState property changes readyState Holds the status of the XMLHttpRequest. 0: request not initialized 1: server connection established 2: request received 3: processing request 4: request finished and response is ready responseText Returns the response data as a string responseXML Returns the response data as XML data status Returns the status-number of a request 200: “OK” 403: “Forbidden” 404: “Not Found” For a complete list go to the Http Messages Reference statusText Returns the status-text (e.g. “OK” or “Not Found”) 1.2.4 编码模板12345if( myRequset.readyState === 4){ if ( (myRequest.status >= 200 && myRquest.status<300)|| myRequst.status == 304 ){ //successful or use local version }} 2 请求2.1 URL 格式1\"name=value&anothername=\"+encodeURIComponent(myVar)+\"&so=on\" 2.2 get、post,适用场景与异同 get请求数据会负载URL之后,把数据放置在HTTP协议头中。 GET在浏览器回退时是无害的 GET请求会被浏览器主动cache GET 请求可被收藏为书签 产生一个TCP数据包 提交的数据量限制于整个URL长度。URL长度根据不同的游览器有不同限制,IE为2083KB。 如果数据是英文字母/数字,原样发送,如果是空格,转换为+,如果是中文/其他字符,则直接把字符串用BASE64加密。 POST把提交的数据则放置在是HTTP包的包体中。 游览器回退POST再次提交请求 POST 请求不会被缓存 POST 请求不会保留在浏览器历史记录中 POST产生两个TCP数据包 POST是没有大小限制的,HTTP协议规范也没有进行大小限制。起限制作用的是服务器的处理程序的处理能力。 POST的安全性要比GET的安全性高 对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);而对于POST,浏览器先发送http header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。 3 关于异步操作问题Q: 如果页面中有两个异步ajax的操作,因为不确定这两个异步操作的执行顺序,怎么在这两个操作都执行完再执行一个新的操作 1.Promise 包装异步ajax操作, 2.定义async 函数, 3.用await等待promise数据异步获取完成 123456789101112131415161718192021222324252627//模拟ajax异步操作1 function ajax1() { const p = new Promise((resolve, reject) => { setTimeout(function() { resolve('ajax 1 has be loaded!') }, 1000) }) return p } //模拟ajax异步操作2 function ajax2() { const p = new Promise((resolve, reject) => { setTimeout(function() { resolve('ajax 2 has be loaded!') }, 2000) }) return p } //等待两个ajax异步操作执行完了后执行的方法 const myFunction = async function() { const x = await ajax1() const y = await ajax2() //等待两个异步ajax请求同时执行完毕后打印出数据 console.log(x, y) } myFunction() 资料引用 JS高级程序设计(第三版) 第21章 AJAX 与 Comet MDN AJAX W3schools AJAX 浅谈HTTP中Get与Post的区别","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"},{"name":"异步","slug":"语言基础/异步","permalink":"http://yoursite.com/categories/语言基础/异步/"}],"tags":[{"name":"ECMA5","slug":"ECMA5","permalink":"http://yoursite.com/tags/ECMA5/"}]},{"title":"ECMA5 继承","slug":"继承","date":"2019-05-22T14:38:04.278Z","updated":"2019-06-11T07:27:03.676Z","comments":true,"path":"2019/05/22/继承/","link":"","permalink":"http://yoursite.com/2019/05/22/继承/","excerpt":"2 继承ECMAScript 只支持实现继承,不支持接口继承。","text":"2 继承ECMAScript 只支持实现继承,不支持接口继承。 继承方法类型: 原型链继承 借用构造函数 组合继承 原型式继承 寄生式继承 寄生组合式继承 2.1 原型链继承 基本思想:利用原型让一个引用类型继承另一个引用类型的属性和方法,实现的本质是重写原型对象,代之一个新类型的实例 原型对象可以算是是一个‘实例’,拥有constructor指针,指向其构造函数 构造函数有prototype指针指向原型对象 实例有__proto__指针执行其原型对象 Father().prototype —> Father.prototype [原型对象] Father.prototype.constructor –> Father() [构造函数] InstanceOfFather.__ proto__ –> Father.prototype 问题: 引用类型的原型属性会被所有实例共享 注意代码块中原型链继承的tips 在创建子类的实例时,不能像超类中的构造函数传递参数 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061 //构造函数 function Father(){ this.name = 'Big Dady'; this.title = 'father'; } //实例方法 Father.prototype.sayName = function (){ console.log(this.name); } //构造函数 function Son(){ this.title = 'son'; this.age = 19; this.objInSonInstance = { sister: 'chesnut' } }//-------------------- tips 原型链继承 存疑中 ----------------------------------- // Son 继承 Father的一个实例 // Father() 中所有属性被衍生类共享 // 只不过普通属性被更改了binding,在实例中拥有了该属性,不会再像原型链搜素 // 引用属性除非是直接更改binding,否则是所有实例都共享了这个属性 Son.prototype = new Father();//------------------------------------------------------------------------------- Son.prototype.objInSon={ brother: 'flag' } //Son的实例方法: !先继承再添加子类的实例方法,不然会被覆盖! Son.prototype.sayTitle = function(){ console.log(this.title); } //在类上的静态方法 Son.staticMethod = function(){ console.log('static!!!'); } //创建Son类的一个实例 instance let instance = new Son(); let instance2 = new Son(); /** instance 的属性搜索链: instance properties: age,title(son),objInSonInstance 以下为原型链层,所有引用的属性会被共享(函数也算对象,对象是引用类型,所有实例共享引用类型、函数) __proto__ properties: name,title(father),sayTitle,objInSon __proto__.__proto__ properties: sayName **/ console.log(instance.hasOwnProperty('title')); //true console.log(instance.__proto__.hasOwnProperty('title')); //true console.log(instance.__proto__.__proto__.hasOwnProperty('sayName')); //true console.log(instance.title, instance.__proto__.title); //son,father console.log(Son.hasOwnProperty('staticMethod')); //true // 实例引用属性,互不影响 instance.objInSonInstance.addInInstance = 'instance add'; console.log(instance.objInSonInstance,instance2.objInSonInstance); //原型上引用属性被共享,instance2.objInSon 被更改 instance.objInSon.addInPrototype = 'prototype add'; console.log(instance.objInSon,instance2.objInSon); 2.2 借用构造函数 借用构造函数并无构成真正意义上的继承 可以传参,引用类型不会被共享,但无法达到函数复用的目的。 1234567891011121314151617181920//借用构造函数 function Super(){ this.refType = [1,2,3]; this.basicType = 'Super basic type';}//Sub不可用该方法Super.prototype.printData = function (property){ console.log(this[property]);}// Sub的原型对象还是objectfunction Sub(){ Super.call(this);}let in1 = new Sub();let in2 = new Sub();console.log(in1.__proto__,Sub.prototype);// object objectin1.printData('refType');//error: not a functionin1.refType.push(1);console.log(in2.refType);//1,2,3 2.3 原型式继承 一个对象作为另外一个对象的继承,原型对象的所有属性被共享,故达到函数复用目的 1234567891011121314151617// 一个对象实例,作为模板let Person = { name:'chochi', // 子类赋值重写,所有看起来不被共享 habbits:['reading','speaking'], print: function(){ console.log(this.name,this.habbits); }}//浅复制let chochi = Object.create(Person);let chesnut = Object.create(Person);chochi.habbits.push('eating');chesnut.print();//reading speaking eatingconsole.log(chesnut.print===chochi.print);// true:函数复用 2.4 组合继承 概念: 使用原型链实现对需要共享的属性和方法的继承 借用构造函数完成实例属性的继承 实例属性屏蔽原型属性 可被 instanceof , isPrototypeOf 识别 融合优点,最常用 问题: 调用两次构造函数,一次是创建子类原型,一次是子类构造函数内部。—》 解决:寄生组合式继承12345678910111213141516171819202122232425 function Father(_title){ this.refTitle ={ title: _title }; } Father.prototype.printProperty = function (){ console.log(this.refTitle); } function Son(_title,_age){ // 借用构造函数:创建实例属性 Father.call(this,_title); this.age = _age; /* 实例属性 property: age, refTitle{title} */ } // 重写原型:共享方法 // 原型上也有了 refTitle 属性,虽然被实例属性屏蔽了,等于一个属性存在了两次 Son.prototype = new Father();//------------ tips --------------------------// 将指针值回来除了逻辑更加清晰其他的改变? Son.prototype.constructor = Son;//-------------------------------------------- 2.5 寄生组合继承 可以直接简化成下面 将组合继承的原型重写那一步改成以下: 如此就不用call两次构造函数,属性也不会被重复 1Son.prototype = Father.prototype;","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"ECMA5","slug":"ECMA5","permalink":"http://yoursite.com/tags/ECMA5/"}]},{"title":"ECMA5 对象","slug":"3 对象","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:26:25.896Z","comments":true,"path":"2019/05/22/3 对象/","link":"","permalink":"http://yoursite.com/2019/05/22/3 对象/","excerpt":"1 键名 对象的所有键名都是字符串,若键名不符合标识符的条件,则必须加上引号。 如果使用方运算符,键名必须放在引号里,否则会被当做变量处理。 数字键可以不加引号,会自动转成字符串。","text":"1 键名 对象的所有键名都是字符串,若键名不符合标识符的条件,则必须加上引号。 如果使用方运算符,键名必须放在引号里,否则会被当做变量处理。 数字键可以不加引号,会自动转成字符串。 123456let obj = { flag: true };obj[flag] // undefinedobj.flag // trueobj.['flag'] // trueflag ='flag';obj[flag] // ture 对象的每一个键名又称为属性 property,它的键值可以是任何数据类型。 2 属性2.1 属性的查看 查看对象本身的所有可枚举属性1Object.keys 2.2 属性的删除 只能删除对象本身的属性,无法删除继承得来的属性。 使用 delete 删除完对象的属性后,Object.keys 方法的返回值也不再包括该属性。 只有一种情况 delete 命令返回 false ,该属性存在但不可删除 configurable:false2.3 属性是否存在 ‘PropertyName’ in obj :是否存在该属性,包括继承而来 hasOwnProperty(‘PropertyName’) :对象本身是拥有该属性2.4 属性的遍历 遍历所有可枚举的属性,包括继承而来的 1for...in 遍历所有可枚举的本身属性(enumerable) 123456// 遍历对象本身属性for( let key in obj){ if( obj.hasOwnProperty(key)){ /* do some operations */ }} 2.5 with 语句 with 语句内只能创建全局变量。 with的绑定对象不明确所以弄临时变量代替with123with( obj ){ /** do operations **/} 遍历总结 for.. in 包括继承而来的可枚举属性 Object.keys 不包括继承的的可枚举属性 Object.getOwnPropertyNames 本身的所有属性","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 数组","slug":"6 Array","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:26:47.266Z","comments":true,"path":"2019/05/22/6 Array/","link":"","permalink":"http://yoursite.com/2019/05/22/6 Array/","excerpt":"1 静态方法1.1 判断是否为数组 使用Array的静态方法 1Array.isArray( array ) 使用原型toString方法,返回的字符串第二个词表示构造函数","text":"1 静态方法1.1 判断是否为数组 使用Array的静态方法 1Array.isArray( array ) 使用原型toString方法,返回的字符串第二个词表示构造函数 1Object.prototype.toString.call( array ) // [object array] instanceof (不太靠谱) 12[] instanceof Object // true[] instanceof Array // true 2 实例方法 valueOf() 返回数组本身 toString() 返回数组字符串形式 push() 在数组的末端添加一个或多个元素 返回数组长度 pop() 删除数组最后一个元素 返回被删除的元素 shift() 删除数组第一个元素 返回被删除的元素 unshitf() 在数组第一个位置添加元素 返回数组长度 实例方法 操作 参数 返回 是否改变原数组 其他 valueOf() 返回数组本身 否 toString() 返回数组字符串形式 否 push() 在数组的末端添加一个或多个元素 添加的元素 返回数组长度 是 pop() 删除数组最后一个元素 无 返回被删除的元素 是 shift() 删除数组第一个元素 无 返回被删除的元素 是 unshitf() 在数组第一个位置添加元素 添加的元素 返回数组长度 是 join() 以参数为分隔符,将数组成员链接为一个字符串 分隔符 返回字符串 否 undefined or null or hole 转为空字符串 cantact() 链接多个数组 数组 返回一个新数组 否 数组浅拷贝(对象涉及引用问题) recerse() 反转数组 无 改变后的数组 是 slice() 提取数组的一部分 start,end(允许负数) 返回新数组 否 参数不合理则返回空数组 splice() 删除原数组的一部分,可在删除的位置添加新成员 start,cnt,addItem1,add.. 返回被删除的元素 是 start接受负数 sort() 对原数组进行排序,默认字典序 自定义比较函数 是 数值也会被默认转为字符串 map() 成员依次执行函数,返回执行结果组成的数组 (fun(item,index,arr),obj)函数后两项可省略,obj用来绑定this 返回结果组成的新数组 否 只跳过hole,undefined & null 不跳过 forEach() 依次执行参数函数,不返回 同上 无 否 无法中断执行,同上 filter() 满足条件的成员组成新数组返回 同上 满足条件的成员组成新数组返回 否 every() 所有成员返回true,则结果返回true 同上 布尔值 否 reduce() 依次处理每个成员,最终累计为一个值 fun(sum,curItem,index,arr)前两个必须 sum 否 indexf() 参数在数组中第一次出现的位置 搜索的元素 下标 or -1 否 内部搜索使用 === 3 example3.1 sort a should be front of b return -1 a is equivalent of b return 0 a should be after of b return 1 123let nums = [1,2,3,11,12];nums.sort(); // Array(5) [1, 11, 12, 2, 3]nums.sort((a,b)=> a-b ); // Array(5) [1, 2, 3, 11, 12]","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 标准库","slug":"5 标准库","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-01T06:26:23.123Z","comments":true,"path":"2019/05/22/5 标准库/","link":"","permalink":"http://yoursite.com/2019/05/22/5 标准库/","excerpt":"1 判断某个变量是否为对象123function isObject(value){ return value === Object(value); } 2 对象的键名","text":"1 判断某个变量是否为对象123function isObject(value){ return value === Object(value); } 2 对象的键名 12Object.keys(instance) // 返回对象本身(不包括继承)的可枚举属性Object.getOwnPropertyNames(instance) // 返回对象本身的所有属性(不包括继承) 3 判断数据类型 toString 返回对象的类型字符串,因此可以用来判断一个值的类型,返回的第一个值表示该值的构造函数。 但由于实力对象可能会自定义该方法,所有调用原型上的方法。1Object.prototype.toString.call( instance ) 4 属性描述对象 value writable 是否可写 enumerable 是否可枚举 值为false时 for..in Object.keys 会跳过该属性 configurable 空值属性描写对象的可写性 get set 1Object.getOwnPropertyDescriptor(obj,PropertyName) // 活动对象本身属性描述对象 12345678910// 使用属性描述对象定义或修改一个属性var obj = Object.defineProperty({},'p',{ value:123, writable:false, enumerable:true, configurable:false});obj.p=456;obj.p; //123 若一个属性的enumerable为false,以下操作不会取到该属性 for ... in Object.keys() 5 对象的拷贝1234567891011var extend = function (to,from){ for( let property in from){ if(!from.hasOwnProperty(property))continue; Object.defineProperty( to, property, Object.getOwnPropertyDescriptor(from,property) // 读不到继承属性的属性描述对象 ); } return to;} 6 控制对象的状态 冻结对象 1234 // 弱到强Object.preventExtensions(obj);// 无法添加新属性Object.seal(obj);// 无法添加or删除属性Object.freeze(obj);//无法添加or删除属性,无法改变属性的值,该对象实际上变成了常量 以上方法,可以改变原型对象,来为对象增加属性","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 面向对象编程","slug":"9 面向对象编程","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:26:57.004Z","comments":true,"path":"2019/05/22/9 面向对象编程/","link":"","permalink":"http://yoursite.com/2019/05/22/9 面向对象编程/","excerpt":"1 实例对象与new 命令1.1 构造函数 函数体内部使用了 this 关键字,代表了所要生成的对象实例。 生成对象的时候,必须使用 new 命令 函数名首字母大写,以示区别。","text":"1 实例对象与new 命令1.1 构造函数 函数体内部使用了 this 关键字,代表了所要生成的对象实例。 生成对象的时候,必须使用 new 命令 函数名首字母大写,以示区别。 1.2 new 命令 执行构造函数,返回一个对象实例。 1.2.1 new 原理1234graph TB A[1.创建一个空对象作为将要返回的对象实例]--> B[2.将这个空对象的原型指向构造函数的prototype属性] B-->C[3.将空对象赋值给函数内部的this关键字] C-->D[4.开始执行构造函数内部的代码] 12345678910111213function _new(constructor,params){ var args = [].slice.call(arguments); var constructor = args.shift(); // 创建一个空对象,继承构造函数的prototype属性 var context = Object.create(constructor.prototype); //执行构造函数 var result = constructor.apply(context, args); //返回结构是对象就直接返回,否则返回一个空对象 return (typeof result === 'object' && result != null) ? result : context;} 1.2.2 new.target 如果当前函数是new命令调用的,new.target指向当前函数,否则为 undefined 使用该属性判断函数调用的时候是否使用了new命令。 2 this 关键字 this 就是属性或方法“当前”所在的对象 this 的指向是可变的 2.1 this 实质1var obj = { foo : 5 }; 1.引擎会在内存中生成一个对象{ foo : 5 } 2.把这个对象的内存地址赋值给变量obj 3.若属性的值是一个函数,引擎会将函数单独保存在内存中,如何再讲函数的地址赋值给foo属性的value属性。 this 的目的在函数体内部,只带函数当前的运行环境。 123456{ foo:{ [[value]]: reference of function .... }} 2.2 this 的使用场合全局环境 只有在全局环节下运行,this就是指顶层对象 window 构造函数 在构造函数中的 this ,指的是实例对象 对象的方法 如果对象的方法里面包含this, this的执行就是方法运行时所在的对象,该方法赋值给另一个对象,就会改变this指向。 若将对象内部或者嵌套对象内部的方法赋值给一个变量,this会指向全局变量。1234567891011121314var a = { b:{ method : function(){ console.log(this); } }, method:function(){ console.log(this); }};var textb = a.b.method;textb(); // windowvar texta = a;a.method(); // object a 在函数中定义的匿名函数的this指向全局对象2.3 绑定 this 使用 call,apply,bind,切换/固定this指向。 bind 函数每运行一次,就返回一个新函数,故监听和回调事件的时候需注意 12345678910111213var counter = { cnt : 0, increament:function(){ 'use strict'; this.cnt++; }}function callIt(callback){ callback();}callIt( counter.increament.bind(counter) ); // 绑定对象,如果直接传函数的referce则this变为windowcounter.cnt; //1 在非 use strict 的情况下可改变为window,在严格模式下报错undefined 1234567891011121314var cnt = 100;var counter = { cnt : 0, increament:function(){ this.cnt++; }}function callIt(callback){ callback();}callIt( counter.increament);// this 指向变为windowconsole.log(counter.cnt,cnt); // 0 101 2.3.1 bind留与call方法使用1234var push = Function.prototype.call.bind(Array.prototype.push);var a = [1,2,3];push(a,4);a; // [1,2,3,4] 3 ES5 对象的继承 js的继承通过“原型对象” prototype 实现。 3.1 原型对象概述 缺点:实例之间无法共享属性 123456789function Cat(_name){ this.name = _name; // 每个实例都会创建一次这个方法 ins1.meow !== ins2.meow // 使用prototype属性解决 this.meow = function(){ console.log('miao!~'); }} 3.2 prototype 属性 定义所有实例对象共享的属性和方法,而实例可以视作从原型对象衍生处理的子对象。 3.3 原型链 prototype chain 所有对象都继承了Object.proto的属性。123// 原型链尽头是 null Object.getPrototypeOf(Object.prototype); // nullObject.prototype.__proto__; // null 等价写法 3.4 constructor 属性 prototype 对象有constructor属性,默认指向prototype对象所在的构造函数。 可以被实例对象继承。使实例对象能被知晓是被哪个构造函数产生。 可以使用 constructor 属性 从一个实例对象新建另一个实例。 constructor属性表示原型对象与构造函数直接的关联关系,如果修改了原型对象,需要同时修改constructor属性。 跳 对象的相关方法","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 包装对象","slug":"7 包装对象 wrapper","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-01T04:27:10.071Z","comments":true,"path":"2019/05/22/7 包装对象 wrapper/","link":"","permalink":"http://yoursite.com/2019/05/22/7 包装对象 wrapper/","excerpt":"1 定义 数值、字符串、布尔值这三种原型类型的值,在一定条件下也会自动转化为对象,也就是原始类型的包装对象。 Number String Boolean 包装对象的目的,使得语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。JS引擎糊自动将原始类型的值转换为包装对象实例,并在使用后立即销毁。 自动转换生成的包装对象是只读的,无法修改。 1234567891011var str = 'abc';str.length; // 3// 等同于var strObj = new String(str);/* String{ 0:\"1\",1:\"b\",2;\"c\",length:3[[PrimitiveValue]]:\"abc\" } strObj.length;//3*/","text":"1 定义 数值、字符串、布尔值这三种原型类型的值,在一定条件下也会自动转化为对象,也就是原始类型的包装对象。 Number String Boolean 包装对象的目的,使得语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。JS引擎糊自动将原始类型的值转换为包装对象实例,并在使用后立即销毁。 自动转换生成的包装对象是只读的,无法修改。 1234567891011var str = 'abc';str.length; // 3// 等同于var strObj = new String(str);/* String{ 0:\"1\",1:\"b\",2;\"c\",length:3[[PrimitiveValue]]:\"abc\" } strObj.length;//3*/ 2 Boolean2.1 if ()12if ( new Boolean(flase)) // true 逻辑运算,所有对象为trueif ( new Boolean(false).valueOf())//false 返回实例原始值 3 正则表达式3.1 建立 字面量方法在引擎编译代码的时候建立正则表达式,所以较为高效12var regex = /xyz/; // 编译时建立var regex = new RegExp('xyz'); // 运行时建立 3.2 实例属性1234567//以下属性只读 // 返回布尔值 是否有设置当前修饰 regex.ignoreCase; regex.global; regex.multiline; // 返回字符串,包含已经设置的所有修饰符,按字母排序 regex.flags; 3.3 实例方法 RegExp.prototype.test() 从 lastIndex 位置向后匹配,找到当前模式能匹配的参数字符串则返回 true 带有g修饰符,每次test()都从上一次结束的位置开始向后匹配1234567891011121314var regex = /x/g;var str = '_x_x__x_';console.log(regex.lastIndex, regex.test(str));// 0 trueconsole.log(regex.lastIndex, regex.test(str));// 2 true// set the value of lastIndex directlyregex.lastIndex = str.length - 1;console.log(regex.lastIndex, regex.test(str));// 7 falsevar num = '1234x';console.log(regex.lastIndex, regex.test(num));// 0 trueconsole.log(regex.lastIndex);// 5 RegExp.prototype.exec() 返回匹配结果(数组) 包含 input index 属性 12345678910var r = /a(b+)a/;var match = r.exec('_abbbbba_aba_');console.log(match);/* Array(2) [\"abbbbba\", \"bbbbb\"] index:1 整个匹配模式成功的开始位置 input:\"_abbbbba_aba_\" 整个字符串 length:2 第二个成员是捕获组匹配结果*/ 3.4 字符串的实例方法 match() 返回匹配结果 若带 g 修饰,则一次性返回所有结果 正则表达式的 lastIndex 属性不造成影响123var s = 'abba_aba_abaa';var r = /a(b+)a/g;var results = s.match(r);//Array(3) [\"abba\", \"aba\", \"aba\"] search() 返回第一个满足条件的匹配结果在整个字符串中的位置 replace(search,replacement) 若带 g 修饰符,则替换所有匹配成功的项","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 函数","slug":"4 函数","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:26:42.221Z","comments":true,"path":"2019/05/22/4 函数/","link":"","permalink":"http://yoursite.com/2019/05/22/4 函数/","excerpt":"1 概述1.1 重复声明 函数的声明会提升到函数定义时所在的作用域的头部。故同名函数会被后来的函数替代。","text":"1 概述1.1 重复声明 函数的声明会提升到函数定义时所在的作用域的头部。故同名函数会被后来的函数替代。 12345678function f(){ console.log('one');}f(); //twofunction f(){ console.log('two');}f(); //two 1.2 函数名的提升 函数声明会提升 12f(); // its okfunction f(){} 函数表达式不提升 使用 var ,var变量提升 ,可识别到变量被声明,但没有定义。 使用 let ,变量未定义。123456789 f(); // f is not a function var f = function(){};//等同于 var f; f(); f = function(){};//使用 let f(); // f is not defined let f = function(){}; 2 函数的属性和方法2.1 name 返回函数的名字2.2 length 返回函数预期传入参数的个数2.3 toString() 返回一个字符串,内容是函数的源码 123456 // 可实现多行字符串 function f(){/* 这是一个 多行注释 */}f.toString() 3 函数作用域3.1 定义 es5 中:全局和函数作用域。 对于 var 命令, 局部变量只能在函数内部声明,其他块区中声明一律为全局变量。3.2 函数内部的变量提升 var,函数声明都会提升到函数体头部3.3 函数本身的作用域 函数本身的作用域就是其声明时所在的作用域,与其运行所在的作用域无关。123456789101112var a = false ;var inside = function(){ console.log(a);}function outside(){ var a = true; inside();}outside(); // false 123456789101112var a = false ;function outside(){ var a = true; var inside = function(){ console.log(a); } inside();}outside(); // true 4 参数 传递方式 passes by value 允许有不定数目的参数4.1 arguments 对象 正常模式下, arguments 允许运行时修改 该对象的 length 属性,可以判断函数调用时到底带几个参数。 callee 属性,指向对应的原函数。 5 闭包 读取函数内部的变量 闭包可以使得诞生环节一直存在,内部变量记住上一次调用时的运算结果 封装对象的私有属性和私有方法 外层函数每次运行,都会生成一个新闭包。每一个闭包变量独立,不共享。 闭包的内存消耗很大,会造成网页的性能问题。 12345678function createIncrementor(start){ return function(){ return start++; }}var ins = createIncrementor(0);ins(); // 0ins(); // 1 6 立即调用的函数表达式 IIFE function 关键字出现在行首一律解释为语句。让引擎理解为表达式,普通的方法是将函数放在括号里。 1(function(){/* code */})(); 不必为函数命名,避免污染全局变量。 形成单独的作用域,封装外部无法读取的私有变量。7 eval 使用别名调用一律为全局作用域。","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 this指针","slug":"关于 this 指针","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:27:11.629Z","comments":true,"path":"2019/05/22/关于 this 指针/","link":"","permalink":"http://yoursite.com/2019/05/22/关于 this 指针/","excerpt":"1 概念 this 对象时运行时基于函数的执行环节绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。 匿名函数的执行环节具有全局性,因此this指针对象通常指向window","text":"1 概念 this 对象时运行时基于函数的执行环节绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。 匿名函数的执行环节具有全局性,因此this指针对象通常指向window 12345678910let obj = { fun : function(){ console.log(this);//obj return function(){ console.log(this);//window 匿名函数有全局性 }; }}; 每个函数在被调用的时候都被自动取得两个特殊的变量:this & arguments 。 内部函数在搜索这两个变量的时候,只会搜索到其活动对象位置,因此不可能直接访问外部函数中的这两个变量。 可以将外部作用域中的this对象保存在一个闭包能访问的变量里1234567891011let obj = { fun : function(){ console.log(this);//obj let that = this; return function(){ console.log(that);//obj 函数闭包把that包括进来 }; } }; 2 加一个关于箭头函数的this指针","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA6 类","slug":"9 JavaScript Classes","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:54:09.225Z","comments":true,"path":"2019/05/22/9 JavaScript Classes/","link":"","permalink":"http://yoursite.com/2019/05/22/9 JavaScript Classes/","excerpt":"Classes1 Class-Like structures in ecma51234567891011121314// propertyfunction PersonType(name){ this.name = name;}// methods: be assigned to the prototype // all instances of the object share the same functionPersonType.prototype.sayName = function(){ console.log(this.name);}let person = new PersonType('chochi');person.sayName();// person is a instance of obeject and PersonType","text":"Classes1 Class-Like structures in ecma51234567891011121314// propertyfunction PersonType(name){ this.name = name;}// methods: be assigned to the prototype // all instances of the object share the same functionPersonType.prototype.sayName = function(){ console.log(this.name);}let person = new PersonType('chochi');person.sayName();// person is a instance of obeject and PersonType 2 Class in ecma62.1 class declarations basic class declaration : the declaration creates a function called constructor method,which is why typeof PersonClass gives “function “ as the result. are NOT hoisted : runs in strict mode automatically methods are NON-enumberable Can overwrite the calss name outside the class but NOT inside a class method . P1961234567891011121314151617class PersonClass{ // proterties can only be created inside a class constructor or method constructor(_name){ this.name = _name; } // methods: equivalent of PersonClass.prototype.sayName sayName(){ console.log(this.name); }}let person = new PersonClass('chochi');person.sayName();// true trueconsole.log(person instanceof PersonClass,person instanceof Object);// fun fun objconsole.log(typeof PersonClass,typeof PersonClass.prototype.sayName,typeof person); 2.2 Named Class Expressions the PersonClass2 identifier exists only within the class definition 1234567891011let PersonClass = class PerconClass2{ constructor(_name){this.name = _name;} sayName(){ // function console.log(typeof PerconClass2); }}let person = new PersonClass('chochi');person.sayName();console.log(typeof PersonClass);// functionconsole.log(typeof PerconClass2);// undefined 2.3 Class Expressions2.3.1 accessor properties123456789class MyHTML{ constructor(_ele){this.ele = ele;} get html(){ return this.ele.innerHTML; } set html(_value){ this.ele.innerHTML = _value; }} 2.3.2 Generator Methodswaiting /// 2.3.3 Static Members1234567891011121314class PersonClass{ constructor(_name){this.name = _name;} // static method: PersonClass.sayName static classSayName(){ console.log(this.name,this); } // instance methos: PersonClass.prototype.intanceSayName intanceSayName(){ console.log(this.name,this); }}let chochi = new PersonClass('chochi');PersonClass.classSayName();// PersonClasschochi.intanceSayName();//chochi 2.3.4 inheritance with derived classes use super() to specify a constructor of derived classes 最好手动在衍生类的构造函数中调用父类的构造函数 子类必须在constructor方法中调用super方法,否则新建实例时会报错。 这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。 ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。 ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。故,在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。 如果子类没有定义constructor方法,默认添加调用父类构造函数,且传入所有参数。 ES6 不会把类的声明提升到代码头部。这种规定的原因与下文要提到的继承有关,必须保证子类在父类之后定义。 Questions1 静态方法和实例方法的区别","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 CALL APPLY 模拟","slug":"Call与Apply","date":"2019-05-22T14:38:04.268Z","updated":"2019-06-11T07:30:13.283Z","comments":true,"path":"2019/05/22/Call与Apply/","link":"","permalink":"http://yoursite.com/2019/05/22/Call与Apply/","excerpt":"概念 190611 更新bind参数问题 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的","text":"概念 190611 更新bind参数问题 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的 区别 apply() 接受两个参数,第一个是运行函数的作用域,第二个是参数数组,参数数组可以用arrary实例,也可以是arguments对象。 call() 参数必须逐个列出来 call 模拟 参数一一对应(没有做一些错误机制的判断处理) 123456789101112Function.prototype.myCall = function(){ let args = Array.from(arguments); const context = args.shift() || window; // null -> window context.callFun = this; // 将函数设置为该对象的一个属性 let result = !args ?context.callFun() : context.callFun(...args); delete context.callFun; return result;} 190611 更新 12345678Function.prototype.myCall = function (){ let args = Array.from(arguments); const context = args.shift() || window; context.func = this; const result = context.fun(...args); delete context.func; return result;} 参数是数组 apply 模拟1234567Function.prototype.myApply = function(_context,array){ let context = _context || window; context.fn = this; let result = !array ? context.fn() : context.fn(...array); delete context.fn; return result;} 190611 更新 1234567Function.prototype.myApply = function(context,args){ context = context || window; context.func = this; const result = context.func(...args); delete context.func; return result;} 实现 bind123456789101112131415161718Function.prototype.myBind = function () { var self = this, // 保存原函数 context = [].shift.call(arguments), // 保存需要绑定的this上下文 args = [].slice.call(arguments); // 剩余的参数转为数组 return function () { // 返回一个新函数 self.apply(context,[...args]); }}var obj = { name: 'chochi'}function func(a,b,c) { console.log(this.name); console.log(a,b,c);}var func1 = func.myBind(obj,1,2,3);func1(); 190611 更新 绑定参数问题 1234567Function.prototype.myBind = function(...args){ const context = args.shift() || window; const self = this; return function(...inner){ self.call(context,...args,...inner); }} 参考文献 JavaScript 中 apply 、call 的详解-linxin","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"},{"name":"已修订","slug":"语言基础/已修订","permalink":"http://yoursite.com/categories/语言基础/已修订/"}],"tags":[{"name":"JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 字符串","slug":"2 字符串","date":"2019-05-22T14:38:04.258Z","updated":"2019-05-22T14:52:15.971Z","comments":true,"path":"2019/05/22/2 字符串/","link":"","permalink":"http://yoursite.com/2019/05/22/2 字符串/","excerpt":"一旦定义无法改变123let str = 'hello';str[1] = '!';console.log(str);// hello 每个字符16位,即2个字节,UTF-16格式存储 length长度放回的可能是不正确的,对于码点在U+1000 - U+10ffff之间的字符,js认为是两字符(es5)","text":"一旦定义无法改变123let str = 'hello';str[1] = '!';console.log(str);// hello 每个字符16位,即2个字节,UTF-16格式存储 length长度放回的可能是不正确的,对于码点在U+1000 - U+10ffff之间的字符,js认为是两字符(es5) Base64 转码 一种编码方法,可以将任意值(只适合ASCII码)转成0~9,A~Z,a~z,+和/这64个个字符组成的可打印字符 主页目的,不是为了加密,而是为了不出现特殊字符,简化程序的处理 12btoa()// 任意值=》Base64atob()// Base64=》原值 12345678// ES5 将 非ASCII码字符转为Base64function b63Encode(str){ return btoa( encodeURIComponent(str)); //非ASCII字符将被十六进制的转义序列进行替换}function b64Decode(str){ return atob(decodeURIComponent(str));}","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA5 数据格式","slug":"1 数据类型","date":"2019-05-22T14:13:19.650Z","updated":"2019-05-22T14:51:59.748Z","comments":true,"path":"2019/05/22/1 数据类型/","link":"","permalink":"http://yoursite.com/2019/05/22/1 数据类型/","excerpt":"1. null & undefined null表示空值,即该处的值为空 undefined 表示为定义,函数没有返回值时,默认返回undefined","text":"1. null & undefined null表示空值,即该处的值为空 undefined 表示为定义,函数没有返回值时,默认返回undefined 12345678910111213141516171819202122232425if(undefined) //falseif(null) //falseif(undefined == null) //trueif(undefined === null) //falseBoolean([]) //trueBoolean({}) //trueBoolean('') //falseBoolean(false) // falsenew Boolean(false) //trueBoolean(null) //falsenew Boolean(null) //true// 转换为数值Number(null) === 0Number(undefined) === NaN// 类型typeof null === object typeof undefined === undefinedtypeof NaN === number 2. 布尔值 除了以下六个值为转换为false ,其他都视为true undefined null false 0 NaN ‘’ or “” 空对象和空数组对应为 true 3. 整数 & 浮点数 所有数值64位浮点数形式存储,故 1===1.0 底层都是小数存储,但某些运算只有整数才能完成,会自动把64浮点数转为32整数。 小数点前数字多于21位或者小数点后的零多于5个,则自动采用科学计数法3.1 进制,内部自动转化为十进制 0b 二进制 0o 八进制 0x 十六进制3.2 +0 & -0 唯一不同,+0 和 -0 当分母时,一个得到+Infinity,一个得到-Infinity3.3 NaN not a number typeof NaN => number NaN 不等于任何值 (NaN !== NaN) =>true Boolean(NaN) => false 与任何数运算都得到本身 Infinity 与 NaN 做比较,任何情况都返回 false 3.4 与数值相关的全局方法3.4.1 parseInt() 将第一个参数转化为字符串,根据第二个参数(2-36,默认为10)的进制转化为整数 每个字符依次转换,遇到不能转为数字的字符,不在进行,直接返回转好的部分,若整个字符串无法转换,返回NaN 对于自动转换为科学计数法的数字会直接对科学计数法当做字符串转换 1234parseInt('567',2);//NaNparseInt(0x10,16);// 结果为22不是16,因为0x10被自动转换为字符串String(0x10);// 16parseInt(0x10,16) => parseInt( String(0x10), 16 ) => parseInt(‘16’,16) 3.4.2 parseFloat() 将一个字符串转为浮点数,接受科学计数法 自动忽略前导零。 3.4.3 isNaN() 判断一个数值是否为NaN 只对数值有效,其他传入值自动转为数值123function myIsNaN( value ){ return value !== value;} 其他 string number(NAN) boolean undefined object(NULL) function symbol","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"}],"tags":[{"name":"-JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]},{"title":"ECMA6 set weakset map","slug":"002set_weakset_map","date":"2019-05-05T15:00:00.000Z","updated":"2019-06-11T07:26:03.968Z","comments":true,"path":"2019/05/05/002set_weakset_map/","link":"","permalink":"http://yoursite.com/2019/05/05/002set_weakset_map/","excerpt":"1 set1.1 set 存值 向 Set 加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。 Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。","text":"1 set1.1 set 存值 向 Set 加入值的时候,不会发生类型转换,所以5和"5"是两个不同的值。 Set 内部判断两个值是否不同,使用的算法叫做“Same-value-zero equality”,它类似于精确相等运算符(===),主要的区别是NaN等于自身,而精确相等运算符认为NaN不等于自身。 1.2 实例属性和方法 实例属性 Set.prototype.constructor:构造函数,默认就是Set函数。 Set.prototype.size:返回Set实例的成员总数。 实例方法 | 操作 add(value):添加某个值,返回 Set 结构本身。 delete(value):删除某个值,返回一个布尔值,表示删除是否成功。 has(value):返回一个布尔值,表示该值是否为Set的成员。 clear():清除所有成员,没有返回值。 实例方法 | 遍历 keys():返回键名的遍历器 values():返回键值的遍历器 entries():返回键值对的遍历器 forEach():使用回调函数遍历每个成员 ps: 由于 Set 结构没有键名,只有键值(或者说键名和键值是同一个值),所以keys方法和values方法的行为完全一致。 Set的遍历顺序就是插入顺序1.3 数组去重 Array.from方法可以将 Set 结构转为数组。 array from方法 12const items = new Set([1, 2, 3, 4, 5]);const array = Array.from(items); 12345function dedupe(array) { return Array.from(new Set(array));}dedupe([1, 1, 2, 3]) // [1, 2, 3] 12// 去除数组的重复成员[...new Set(array)] 1.4 遍历操作 Set的遍历顺序就是插入顺序。 使用 Set 保存一个回调函数列表,调用时就能保证按照添加顺序调用。 Set 结构的实例默认可遍历,它的默认遍历器生成函数就是它的values方法。可以省略values方法,直接用for...of循环遍历 Set。 12345678let set = new Set(['red', 'green', 'blue']);for (let x of set) { console.log(x);}// red// green// blue 使用 Set 可实现并集(Union)、交集(Intersect)和差集(Difference) 1234567891011121314let a = new Set([1, 2, 3]);let b = new Set([4, 3, 2]);// 并集let union = new Set([...a, ...b]);// Set {1, 2, 3, 4}// 交集let intersect = new Set([...a].filter(x => b.has(x)));// set {2, 3}// 差集let difference = new Set([...a].filter(x => !b.has(x)));// Set {1} 1.4 WeakSet WeakSet 的成员只能是对象,而不能是其他类型的值。 WeakSet 不可遍历,(即没有keys()、values()和entries()方法),也没有size属性。无法清空,即不支持clear方法。 WeakMap只有四个方法可用:get()、set()、has()、delete()。 WeakSet 适合临时存放一组对象,以及存放跟对象绑定的信息。只要这些对象在外部消失,它在 WeakSet 里面的引用就会自动消失。 WeakSet 中的对象都是弱引用,即垃圾回收机制不考虑 WeakSet 对该对象的引用,也就是说,如果其他对象都不再引用该对象,那么垃圾回收机制会自动回收该对象所占用的内存,不考虑该对象还存在于 WeakSet 之中。( WeakMap 弱引用的只是键名,而不是键值。键值依然是正常引用。) 如果你要往对象上添加数据,又不想干扰垃圾回收机制,就可以使用 WeakMap。一个典型应用场景是,在网页的 DOM 元素上添加数据,就可以使用WeakMap结构。当该 DOM 元素被清除,其所对应的WeakMap记录就会自动被移除。 1234567891011const foos = new WeakSet()class Foo { constructor() { foos.add(this) } method () { if (!foos.has(this)) { throw new TypeError('Foo.prototype.method 只能在Foo的实例上调用!'); } }} 上面代码保证了Foo的实例方法,只能在Foo的实例上调用。这里使用 WeakSet 的好处是,foos对实例的引用,不会被计入内存回收机制,所以删除实例的时候,不用考虑foos,也不会出现内存泄漏。 2 Map Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应 任何具有 Iterator 接口、且每个成员都是一个双元素的数组的数据结构(都可以当作Map构造函数的参数。这就是说,Set和Map都可以用来生成新的 Map。 如果对同一个键多次赋值,后面的值将覆盖前面的值。 1234567const map = new Map();map.set(1, 'aaa').set(1, 'bbb');map.get(1) // \"bbb\" 只有对同一个对象的引用,Map 结构才将其视为同一个键。这一点要非常小心。 1234const map = new Map();map.set(['a'], 555);map.get(['a']) // undefined 上面代码的set和get方法,表面是针对同一个键,但实际上这是两个值,内存地址是不一样的,因此get方法无法读取该键,返回undefined。 Map 的键实际上是跟内存地址绑定的,只要内存地址不一样,就视为两个键。这就解决了同名属性碰撞(clash)的问题,我们扩展别人的库的时候,如果使用对象作为键名,就不用担心自己的属性与原作者的属性同名。","categories":[{"name":"语言基础","slug":"语言基础","permalink":"http://yoursite.com/categories/语言基础/"},{"name":"ECMA6","slug":"语言基础/ECMA6","permalink":"http://yoursite.com/categories/语言基础/ECMA6/"}],"tags":[{"name":"JS","slug":"JS","permalink":"http://yoursite.com/tags/JS/"}]}]}