diff --git a/2019/05/05/002set_weakset_map/index.html b/2019/05/05/002set_weakset_map/index.html new file mode 100644 index 0000000..f8f9223 --- /dev/null +++ b/2019/05/05/002set_weakset_map/index.html @@ -0,0 +1,477 @@ + + + + + + + + + ECMA6 set weakset map | chochi's workshop + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+
+ +
+
+
+ + + + + + +
+
+ + + + + + + + + + + + +
    + + + + + + + +
  • ME
  • + + +
+
+
+ + + + + +
+ +
chochi <br/> 福州大学在读研究生 <br/>
+ +
+ +
+ +
+ + +
+ + \ No newline at end of file diff --git "a/2019/05/22/2 \345\255\227\347\254\246\344\270\262/index.html" "b/2019/05/22/2 \345\255\227\347\254\246\344\270\262/index.html" index 9a607ae..dbad318 100644 --- "a/2019/05/22/2 \345\255\227\347\254\246\344\270\262/index.html" +++ "b/2019/05/22/2 \345\255\227\347\254\246\344\270\262/index.html" @@ -216,11 +216,11 @@

- +
- ECMA5 CALL APPLY 模拟 + ECMA5 数组
diff --git "a/2019/05/22/3 \345\257\271\350\261\241/index.html" "b/2019/05/22/3 \345\257\271\350\261\241/index.html" index d79adcc..c998b32 100644 --- "a/2019/05/22/3 \345\257\271\350\261\241/index.html" +++ "b/2019/05/22/3 \345\257\271\350\261\241/index.html" @@ -250,18 +250,18 @@

- +
- ECMA5 标准库 + ECMA5 继承
- -
ECMA6 类
+
+
ECMA5 this指针
diff --git "a/2019/05/22/4 \345\207\275\346\225\260/index.html" "b/2019/05/22/4 \345\207\275\346\225\260/index.html" index 916dad1..4d7368d 100644 --- "a/2019/05/22/4 \345\207\275\346\225\260/index.html" +++ "b/2019/05/22/4 \345\207\275\346\225\260/index.html" @@ -265,11 +265,11 @@

- +
- ECMA5 包装对象 + ECMA5 CALL APPLY 模拟
diff --git "a/2019/05/22/5 \346\240\207\345\207\206\345\272\223/index.html" "b/2019/05/22/5 \346\240\207\345\207\206\345\272\223/index.html" index e72d976..1f15359 100644 --- "a/2019/05/22/5 \346\240\207\345\207\206\345\272\223/index.html" +++ "b/2019/05/22/5 \346\240\207\345\207\206\345\272\223/index.html" @@ -249,8 +249,8 @@

-
ECMA5 对象
+
+
ECMA5 面向对象编程
diff --git a/2019/05/22/6 Array/index.html b/2019/05/22/6 Array/index.html index f51ea07..ec65eac 100644 --- a/2019/05/22/6 Array/index.html +++ b/2019/05/22/6 Array/index.html @@ -249,18 +249,18 @@

- +
- ECMA5 继承 + ECMA6 类
- -
ECMA5 包装对象
+
+
ECMA5 字符串
diff --git "a/2019/05/22/7 \345\214\205\350\243\205\345\257\271\350\261\241 wrapper/index.html" "b/2019/05/22/7 \345\214\205\350\243\205\345\257\271\350\261\241 wrapper/index.html" index bee0ecf..7fe3bc7 100644 --- "a/2019/05/22/7 \345\214\205\350\243\205\345\257\271\350\261\241 wrapper/index.html" +++ "b/2019/05/22/7 \345\214\205\350\243\205\345\257\271\350\261\241 wrapper/index.html" @@ -256,18 +256,18 @@

- +
- ECMA5 数组 + ECMA5 面向对象编程
- -
ECMA5 函数
+
+
ECMA6 类
diff --git a/2019/05/22/9 JavaScript Classes/index.html b/2019/05/22/9 JavaScript Classes/index.html index 138ec66..bf79f88 100644 --- a/2019/05/22/9 JavaScript Classes/index.html +++ b/2019/05/22/9 JavaScript Classes/index.html @@ -236,18 +236,18 @@

- +
- ECMA5 对象 + ECMA5 包装对象
- -
ECMA5 this指针
+
+
ECMA5 数组
diff --git "a/2019/05/22/9 \351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213/index.html" "b/2019/05/22/9 \351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213/index.html" index adee187..9c4c7fe 100644 --- "a/2019/05/22/9 \351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213/index.html" +++ "b/2019/05/22/9 \351\235\242\345\220\221\345\257\271\350\261\241\347\274\226\347\250\213/index.html" @@ -277,18 +277,18 @@

- +
- ECMA5 this指针 + ECMA5 标准库
- -
ECMA5 CALL APPLY 模拟
+
+
ECMA5 包装对象
diff --git "a/2019/05/22/Call\344\270\216Apply/index.html" "b/2019/05/22/Call\344\270\216Apply/index.html" index 2e38cf7..1b346cb 100644 --- "a/2019/05/22/Call\344\270\216Apply/index.html" +++ "b/2019/05/22/Call\344\270\216Apply/index.html" @@ -234,18 +234,18 @@

- +
- ECMA5 面向对象编程 + ECMA5 this指针
- -
ECMA5 字符串
+
+
ECMA5 函数
diff --git a/2019/05/22/hello-world/index.html b/2019/05/22/hello-world/index.html index c173560..00e82ee 100644 --- a/2019/05/22/hello-world/index.html +++ b/2019/05/22/hello-world/index.html @@ -202,6 +202,11 @@

+
ECMA6 set weakset map
+ +
+ diff --git "a/2019/05/22/\345\205\263\344\272\216 this \346\214\207\351\222\210/index.html" "b/2019/05/22/\345\205\263\344\272\216 this \346\214\207\351\222\210/index.html" index 5b45fa8..79c3363 100644 --- "a/2019/05/22/\345\205\263\344\272\216 this \346\214\207\351\222\210/index.html" +++ "b/2019/05/22/\345\205\263\344\272\216 this \346\214\207\351\222\210/index.html" @@ -219,18 +219,18 @@

- +
- ECMA6 类 + ECMA5 对象
- -
ECMA5 面向对象编程
+
+
ECMA5 CALL APPLY 模拟
diff --git "a/2019/05/22/\347\273\247\346\211\277/index.html" "b/2019/05/22/\347\273\247\346\211\277/index.html" index e6217e2..1ec7ece 100644 --- "a/2019/05/22/\347\273\247\346\211\277/index.html" +++ "b/2019/05/22/\347\273\247\346\211\277/index.html" @@ -275,8 +275,8 @@

-
ECMA5 数组
+
+
ECMA5 对象
diff --git a/archives/2019/05/index.html b/archives/2019/05/index.html index 5a2e4e0..cc809ff 100644 --- a/archives/2019/05/index.html +++ b/archives/2019/05/index.html @@ -306,14 +306,14 @@

- ECMA5 数组 + ECMA5 对象

@@ -355,14 +355,14 @@

- ECMA5 包装对象 + ECMA5 this指针

@@ -404,14 +404,14 @@

- ECMA5 函数 + ECMA5 CALL APPLY 模拟

@@ -453,14 +453,14 @@

- ECMA5 标准库 + ECMA5 函数

@@ -502,14 +502,14 @@

- ECMA5 对象 + ECMA5 标准库

@@ -551,14 +551,14 @@

- ECMA6 类 + ECMA5 面向对象编程

@@ -600,14 +600,14 @@

- ECMA5 this指针 + ECMA5 包装对象

diff --git a/archives/2019/05/page/2/index.html b/archives/2019/05/page/2/index.html index a9b6565..481d99e 100644 --- a/archives/2019/05/page/2/index.html +++ b/archives/2019/05/page/2/index.html @@ -155,14 +155,14 @@

chochi

- ECMA5 面向对象编程 + ECMA6 类

@@ -204,14 +204,14 @@

- ECMA5 CALL APPLY 模拟 + ECMA5 数组

@@ -372,6 +372,59 @@

+ + + +

diff --git a/archives/2019/index.html b/archives/2019/index.html index 8ee4a1c..ad2ceae 100644 --- a/archives/2019/index.html +++ b/archives/2019/index.html @@ -306,14 +306,14 @@

- ECMA5 数组 + ECMA5 对象

@@ -355,14 +355,14 @@

- ECMA5 包装对象 + ECMA5 this指针

@@ -404,14 +404,14 @@

- ECMA5 函数 + ECMA5 CALL APPLY 模拟

@@ -453,14 +453,14 @@

- ECMA5 标准库 + ECMA5 函数

@@ -502,14 +502,14 @@

- ECMA5 对象 + ECMA5 标准库

@@ -551,14 +551,14 @@

- ECMA6 类 + ECMA5 面向对象编程

@@ -600,14 +600,14 @@

- ECMA5 this指针 + ECMA5 包装对象

diff --git a/archives/2019/page/2/index.html b/archives/2019/page/2/index.html index 35414b5..fed6196 100644 --- a/archives/2019/page/2/index.html +++ b/archives/2019/page/2/index.html @@ -155,14 +155,14 @@

chochi

- ECMA5 面向对象编程 + ECMA6 类

@@ -204,14 +204,14 @@

- ECMA5 CALL APPLY 模拟 + ECMA5 数组

@@ -372,6 +372,59 @@

+ + + +

diff --git a/archives/index.html b/archives/index.html index 4d78097..86a70ee 100644 --- a/archives/index.html +++ b/archives/index.html @@ -306,14 +306,14 @@

- ECMA5 数组 + ECMA5 对象

@@ -355,14 +355,14 @@

- ECMA5 包装对象 + ECMA5 this指针

@@ -404,14 +404,14 @@

- ECMA5 函数 + ECMA5 CALL APPLY 模拟

@@ -453,14 +453,14 @@

- ECMA5 标准库 + ECMA5 函数

@@ -502,14 +502,14 @@

- ECMA5 对象 + ECMA5 标准库

@@ -551,14 +551,14 @@

- ECMA6 类 + ECMA5 面向对象编程

@@ -600,14 +600,14 @@

- ECMA5 this指针 + ECMA5 包装对象

diff --git a/archives/page/2/index.html b/archives/page/2/index.html index 0098734..f85eb8b 100644 --- a/archives/page/2/index.html +++ b/archives/page/2/index.html @@ -155,14 +155,14 @@

chochi

- ECMA5 面向对象编程 + ECMA6 类

@@ -204,14 +204,14 @@

- ECMA5 CALL APPLY 模拟 + ECMA5 数组

@@ -372,6 +372,59 @@

+ + + +

diff --git "a/categories/\350\257\255\350\250\200\345\237\272\347\241\200/ECMA6/index.html" "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/ECMA6/index.html" new file mode 100644 index 0000000..bbd63f2 --- /dev/null +++ "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/ECMA6/index.html" @@ -0,0 +1,361 @@ + + + + + + + + + Category: ECMA6 | chochi's workshop + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+
+ +
+ +
+
+ + + +
+ +
+
+
+ +
+
+
+ + + + + + +
+
+ + + + + + + + + + + + +
    + + + + + + + +
  • ME
  • + + +
+
+
+ + + + + +
+ +
chochi <br/> 福州大学在读研究生 <br/>
+ +
+ +
+ +
+ + +
+ + \ No newline at end of file diff --git "a/categories/\350\257\255\350\250\200\345\237\272\347\241\200/index.html" "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/index.html" index 550df5a..4abd5bb 100644 --- "a/categories/\350\257\255\350\250\200\345\237\272\347\241\200/index.html" +++ "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/index.html" @@ -257,14 +257,14 @@

- ECMA6 类 + ECMA5 数组

@@ -306,14 +306,14 @@

- ECMA5 包装对象 + ECMA5 this指针

@@ -355,14 +355,14 @@

- ECMA5 函数 + ECMA5 对象

@@ -404,14 +404,14 @@

- ECMA5 标准库 + ECMA5 函数

@@ -453,14 +453,14 @@

- ECMA5 对象 + ECMA5 标准库

@@ -502,14 +502,14 @@

- ECMA5 this指针 + ECMA5 CALL APPLY 模拟

@@ -551,14 +551,14 @@

- ECMA5 数组 + ECMA5 包装对象

@@ -600,14 +600,14 @@

- ECMA5 面向对象编程 + ECMA6 类

diff --git "a/categories/\350\257\255\350\250\200\345\237\272\347\241\200/page/2/index.html" "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/page/2/index.html" index 5b8b447..8cba97c 100644 --- "a/categories/\350\257\255\350\250\200\345\237\272\347\241\200/page/2/index.html" +++ "b/categories/\350\257\255\350\250\200\345\237\272\347\241\200/page/2/index.html" @@ -155,14 +155,14 @@

chochi

- ECMA5 CALL APPLY 模拟 + ECMA5 面向对象编程

@@ -296,6 +296,59 @@

+ + + +
diff --git a/content.json b/content.json index ccaa9e6..fe02295 100644 --- a/content.json +++ b/content.json @@ -1 +1 @@ -{"meta":{"title":"chochi's workshop","subtitle":null,"description":null,"author":"chochi","url":"http://yoursite.com","root":"/"},"pages":[{"title":"","date":"2019-05-26T08:19:23.824Z","updated":"2019-05-26T08:19:23.824Z","comments":true,"path":"showcase/showcase.html","permalink":"http://yoursite.com/showcase/showcase.html","excerpt":"","text":"chochi's workshop BallGame(正常) IamgeSlider FlexLayout JSONandAJAX(正常) 嵌入框架后项目就乱码了T T 寻找解决方法中"}],"posts":[{"title":"React state更新","slug":"001react_state_update","date":"2019-05-26T13:39:00.347Z","updated":"2019-05-26T13:43:30.103Z","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函数刷新12// 正确this.setState({title: 'React'}); 2 state更新2.1 state 更新 setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。","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的eventloop简单的来说可以划分执行顺序为 同步-> 异步->回调 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-05-24T14:25:25.675Z","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":"6 Array","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-24T14:26:35.794Z","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 | 否|内部搜索使用 ===|","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-05-22T14:49:12.973Z","comments":true,"path":"2019/05/22/7 包装对象 wrapper/","link":"","permalink":"http://yoursite.com/2019/05/22/7 包装对象 wrapper/","excerpt":"1 定义 数值、字符串、布尔值这三种原型类型的值,在一听条件下也会自动转化为对象,也就是原始类型的包装对象。 Number String Boolean 包装对象的目的,是得对象模型覆盖js所优质,正门语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。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所优质,正门语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。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()都从上一次结束的位置开始向后匹配1234567var regex = /r/g;var str = '_x_x';regex.lastIndex ; // 0regex.test(s); //trueregex.lastIndex; // 2 _regex.lastIdex = 4; // 可指定搜索位置,只对同一个正则表达式有效regex.test(s); //false 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-05-22T14:53:07.745Z","comments":true,"path":"2019/05/22/4 函数/","link":"","permalink":"http://yoursite.com/2019/05/22/4 函数/","excerpt":"1 概述1.1 重复声明 函数的声明会提升到函数定义时所在的作用域的头部。故同名函数会被后来的函数替代。 12345678function f(){ console.log('one');}f(); //twofunction f(){ console.log('two');}f(); //two","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 标准库","slug":"5 标准库","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:53:23.277Z","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 // 返回对象本身(不包括继承)的可枚举属性Object.getOwnPropertyNames // 返回对象本身的所有属性(不包括继承) 3 判断数据类型 toString 返回对象的类型字符串,因此可以用来判断一个值的类型,返回的第一个值表示该值的构造函数。 但由于实力对象可能会自定义该方法,所有调用原型上的方法。1Object.prototype.toString.call(value) 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":"3 对象","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:52:44.830Z","comments":true,"path":"2019/05/22/3 对象/","link":"","permalink":"http://yoursite.com/2019/05/22/3 对象/","excerpt":"1 键名 对象的所有键名都是字符串,若键名不符合标识符的条件,则必须加上引号。 如果使用方运算符,键名必须放在引号里,否则会被当做变量处理。 数字键可以不加引号,会自动转成字符串。123456let obj = { flag: true };obj[flag] // undefinedobj.flag // trueobj.['flag'] // trueflag ='flag';obj[flag] // ture","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":"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 this指针","slug":"关于 this 指针","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-26T13:37:31.060Z","comments":true,"path":"2019/05/22/关于 this 指针/","link":"","permalink":"http://yoursite.com/2019/05/22/关于 this 指针/","excerpt":"1 概念 this 对象时运行时基于函数的执行环节绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。 匿名函数的执行环节具有全局性,因此this指针对象通常指向window 12345678910let obj = { fun : function(){ console.log(this);//obj return function(){ console.log(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":"ECMA5 面向对象编程","slug":"9 面向对象编程","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:48:49.890Z","comments":true,"path":"2019/05/22/9 面向对象编程/","link":"","permalink":"http://yoursite.com/2019/05/22/9 面向对象编程/","excerpt":"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.开始执行构造函数内部的代码]","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 CALL APPLY 模拟","slug":"Call与Apply","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:54:34.598Z","comments":true,"path":"2019/05/22/Call与Apply/","link":"","permalink":"http://yoursite.com/2019/05/22/Call与Apply/","excerpt":"概念 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的区别 apply() 接受两个参数,第一个是运行函数的作用域,第二个是参数数组,参数数组可以用arrar实例,也可以是arguments对象。 call() 参数必须逐个列出来 call 模拟 参数一一对应 12345678Function.prototype.myCall = function(_context){ let context = _context || window;// null -> window context.fn = this; let args = [].slice.call(arguments,1,arguments.length); let result = !args ?context.fn():context.fn(...args); delete context.fn; return result;}","text":"概念 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的区别 apply() 接受两个参数,第一个是运行函数的作用域,第二个是参数数组,参数数组可以用arrar实例,也可以是arguments对象。 call() 参数必须逐个列出来 call 模拟 参数一一对应 12345678Function.prototype.myCall = function(_context){ let context = _context || window;// null -> window context.fn = this; let args = [].slice.call(arguments,1,arguments.length); let result = !args ?context.fn():context.fn(...args); delete context.fn; 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;} 实现 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(); 参考文献 JavaScript 中 apply 、call 的详解-linxin","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":"Hello World","slug":"hello-world","date":"2019-05-22T12:55:46.832Z","updated":"2019-05-22T12:55:46.832Z","comments":true,"path":"2019/05/22/hello-world/","link":"","permalink":"http://yoursite.com/2019/05/22/hello-world/","excerpt":"","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[]}]} \ No newline at end of file +{"meta":{"title":"chochi's workshop","subtitle":null,"description":null,"author":"chochi","url":"http://yoursite.com","root":"/"},"pages":[{"title":"","date":"2019-05-26T08:19:23.824Z","updated":"2019-05-26T08:19:23.824Z","comments":true,"path":"showcase/showcase.html","permalink":"http://yoursite.com/showcase/showcase.html","excerpt":"","text":"chochi's workshop BallGame(正常) IamgeSlider FlexLayout JSONandAJAX(正常) 嵌入框架后项目就乱码了T T 寻找解决方法中"}],"posts":[{"title":"React state更新","slug":"001react_state_update","date":"2019-05-26T13:39:00.347Z","updated":"2019-05-26T13:43:30.103Z","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函数刷新12// 正确this.setState({title: 'React'}); 2 state更新2.1 state 更新 setState 只在合成事件和钩子函数中是“异步”的,在原生事件和 setTimeout 中都是同步的。setState的“异步”并不是说内部由异步代码实现,其实本身执行的过程和代码都是同步的,只是合成事件和钩子函数的调用顺序在更新之前,导致在合成事件和钩子函数中没法立马拿到更新后的值,形式了所谓的“异步”,当然可以通过第二个参数 setState(partialState, callback) 中的callback拿到更新后的结果。","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的eventloop简单的来说可以划分执行顺序为 同步-> 异步->回调 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-05-24T14:25:25.675Z","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-05-22T14:52:44.830Z","comments":true,"path":"2019/05/22/3 对象/","link":"","permalink":"http://yoursite.com/2019/05/22/3 对象/","excerpt":"1 键名 对象的所有键名都是字符串,若键名不符合标识符的条件,则必须加上引号。 如果使用方运算符,键名必须放在引号里,否则会被当做变量处理。 数字键可以不加引号,会自动转成字符串。123456let obj = { flag: true };obj[flag] // undefinedobj.flag // trueobj.['flag'] // trueflag ='flag';obj[flag] // ture","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 this指针","slug":"关于 this 指针","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-26T13:37:31.060Z","comments":true,"path":"2019/05/22/关于 this 指针/","link":"","permalink":"http://yoursite.com/2019/05/22/关于 this 指针/","excerpt":"1 概念 this 对象时运行时基于函数的执行环节绑定的,在全局函数中,this等于window,而当函数被作为某个对象的方法调用时,this等于那个对象。 匿名函数的执行环节具有全局性,因此this指针对象通常指向window 12345678910let obj = { fun : function(){ console.log(this);//obj return function(){ console.log(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":"ECMA5 CALL APPLY 模拟","slug":"Call与Apply","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:54:34.598Z","comments":true,"path":"2019/05/22/Call与Apply/","link":"","permalink":"http://yoursite.com/2019/05/22/Call与Apply/","excerpt":"概念 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的区别 apply() 接受两个参数,第一个是运行函数的作用域,第二个是参数数组,参数数组可以用arrar实例,也可以是arguments对象。 call() 参数必须逐个列出来 call 模拟 参数一一对应 12345678Function.prototype.myCall = function(_context){ let context = _context || window;// null -> window context.fn = this; let args = [].slice.call(arguments,1,arguments.length); let result = !args ?context.fn():context.fn(...args); delete context.fn; return result;}","text":"概念 每个函数都包括两个非继承而来的方法 apply call 在特定的作用域中调用函数,实际上等于设置函数体内this对象的值 看出 call 和 apply 是为了动态改变 this 而出现的区别 apply() 接受两个参数,第一个是运行函数的作用域,第二个是参数数组,参数数组可以用arrar实例,也可以是arguments对象。 call() 参数必须逐个列出来 call 模拟 参数一一对应 12345678Function.prototype.myCall = function(_context){ let context = _context || window;// null -> window context.fn = this; let args = [].slice.call(arguments,1,arguments.length); let result = !args ?context.fn():context.fn(...args); delete context.fn; 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;} 实现 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(); 参考文献 JavaScript 中 apply 、call 的详解-linxin","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-05-22T14:53:07.745Z","comments":true,"path":"2019/05/22/4 函数/","link":"","permalink":"http://yoursite.com/2019/05/22/4 函数/","excerpt":"1 概述1.1 重复声明 函数的声明会提升到函数定义时所在的作用域的头部。故同名函数会被后来的函数替代。 12345678function f(){ console.log('one');}f(); //twofunction f(){ console.log('two');}f(); //two","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 标准库","slug":"5 标准库","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-22T14:53:23.277Z","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 // 返回对象本身(不包括继承)的可枚举属性Object.getOwnPropertyNames // 返回对象本身的所有属性(不包括继承) 3 判断数据类型 toString 返回对象的类型字符串,因此可以用来判断一个值的类型,返回的第一个值表示该值的构造函数。 但由于实力对象可能会自定义该方法,所有调用原型上的方法。1Object.prototype.toString.call(value) 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-05-22T14:48:49.890Z","comments":true,"path":"2019/05/22/9 面向对象编程/","link":"","permalink":"http://yoursite.com/2019/05/22/9 面向对象编程/","excerpt":"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.开始执行构造函数内部的代码]","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-05-22T14:49:12.973Z","comments":true,"path":"2019/05/22/7 包装对象 wrapper/","link":"","permalink":"http://yoursite.com/2019/05/22/7 包装对象 wrapper/","excerpt":"1 定义 数值、字符串、布尔值这三种原型类型的值,在一听条件下也会自动转化为对象,也就是原始类型的包装对象。 Number String Boolean 包装对象的目的,是得对象模型覆盖js所优质,正门语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。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所优质,正门语言都有一个通用的数据模型,其次是得原始类型的值也有可以调动自己的方法。 原始类型的值会自动当做包装对象调用,即调用包装对象的属性和方法。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()都从上一次结束的位置开始向后匹配1234567var regex = /r/g;var str = '_x_x';regex.lastIndex ; // 0regex.test(s); //trueregex.lastIndex; // 2 _regex.lastIdex = 4; // 可指定搜索位置,只对同一个正则表达式有效regex.test(s); //false 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":"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 数组","slug":"6 Array","date":"2019-05-22T14:38:04.268Z","updated":"2019-05-24T14:26:35.794Z","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 | 否|内部搜索使用 ===|","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":"Hello World","slug":"hello-world","date":"2019-05-22T12:55:46.832Z","updated":"2019-05-22T12:55:46.832Z","comments":true,"path":"2019/05/22/hello-world/","link":"","permalink":"http://yoursite.com/2019/05/22/hello-world/","excerpt":"","text":"Welcome to Hexo! This is your very first post. Check documentation for more info. If you get any problems when using Hexo, you can find the answer in troubleshooting or you can ask me on GitHub. Quick StartCreate a new post1$ hexo new \"My New Post\" More info: Writing Run server1$ hexo server More info: Server Generate static files1$ hexo generate More info: Generating Deploy to remote sites1$ hexo deploy More info: Deployment","categories":[],"tags":[]},{"title":"ECMA6 set weakset map","slug":"002set_weakset_map","date":"2019-05-05T15:00:00.000Z","updated":"2019-05-27T14:06:06.452Z","comments":true,"path":"2019/05/05/002set_weakset_map/","link":"","permalink":"http://yoursite.com/2019/05/05/002set_weakset_map/","excerpt":"","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/"}]}]} \ No newline at end of file diff --git a/index.html b/index.html index 570a733..c128abb 100644 --- a/index.html +++ b/index.html @@ -425,19 +425,19 @@

2 -
+

- ECMA5 数组 + ECMA5 对象

- @@ -445,19 +445,19 @@

-

1 静态方法

1.1 判断是否为数组

    -
  1. 使用Array的静态方法
  2. -
-
1
Array.isArray( array )
-
    -
  1. 使用原型toString方法,返回的字符串第二个词表示构造函数 +

    1 键名

      +
    • 对象的所有键名都是字符串,若键名不符合标识符的条件,则必须加上引号。
    • +
    • 如果使用方运算符,键名必须放在引号里,否则会被当做变量处理。
    • +
    • 数字键可以不加引号,会自动转成字符串。
      1
      2
      3
      4
      5
      6
      let obj  = { flag: true };
      obj[flag] // undefined
      obj.flag // true
      obj.['flag'] // true
      flag ='flag';
      obj[flag] // ture
      +
    • +
    - more >> + more >> -
+