Javascript
从 HTML5 学习笔记独立出,沿用习惯用语 JS 是 ES6 的一种实现。
Learning material#
Syntax#
resouces:#
- https://es6.ruanyifeng.com/
- Promise (also for async)
book#
https://bonsaiden.github.io/JavaScript-Garden/ https://johnresig.com/apps/learn/ https://eloquentjavascript.net/
Syntax Learning Note#
Promise#
AKA: passing return outside callback
1 2 3 4 |
|
E.g. in fetch :
1 2 3 4 5 6 7 8 9 10 11 |
|
https://es6.ruanyifeng.com/#docs/async#%E8%AF%AD%E6%B3%95
Master ruanyifeng tells us use more async
than Promise
. (async
is prefered)
Promise in Debug
- Catch statement does not catch thrown error: https://stackoverflow.com/questions/16316815/catch-statement-does-not-catch-thrown-error
The reason why your
try catch
block is failing is because anajax
request is asynchronous. Thetry catch
block will execute before the Ajax call and send therequest
itself, but theerror
is thrown when the result is returned, AT A LATER POINT IN TIME. When thetry catch
block is executed, there is no error. When the error is thrown, there is notry catch
. If you needtry catch
forajax
requests, always putajax
try catch blocks inside the success callback, NEVER outside of it.
Array#
- for an accumulative iteration, use
Array.reduce()
instead ofArray.forEach()
Blob#
blob types:
1 2 |
|
Typed Array#
- like Uint8Array Uint16Array
Uint8Array.name
string value of the constructor nameUint8Array
Uint8Array.prototype.buffer
convert to arraybuffer
ArrayBuffer & TypedArray#
const buffer = new ArrayBuffer(8); const uint16 = new Uint16Array(buffer);
This is like new Array(onearg)
, which defines the length.
encoding an TypedArray
#
- From topic: encoding a blob. first tried
FileReader
: https://developer.mozilla.org/en-US/docs/Web/API/FileReader. from https://medium.com/programmers-developers/convert-blob-to-string-in-javascript-944c15ad7d52 TextDecoder
andTextDecoder
for encoding an Uint8Array wont work if the Array has an element like 255,243,88 etc-
String: works either:
JS encoded = String.fromCharCode.apply(null, u8) decoded = encoded.split('').map(c=>c.charCodeAt(0))
but, with U16, it works. from https://developers.google.com/web/updates/2012/06/How-to-convert-ArrayBuffer-to-and-from-String (search array buffer to string instead of
U8intArray
)
Uint8Array & Array :
1 2 |
|
callback function:#
JS 中可以 return 一个 function,(调用该 function 而不是 return 这个 function 的 return 值)
scrollTop#
Scrolltop Property 2019-11-14 04:22:47 scrollIntoView 作用类似微信中的 scroll-into view element.scrollIntoView();会移动整个页面,想只移动 div 中的内容要用 element. scrollTop scrollTop 是元素的属性,控制(滚动)的是外面的 scrollable div。
https://stackoverflow.com/a/1592609/10942184 You need to get the top offset of the element you'd like to scroll into view, relative to its parent (the scrolling div container): var myElement = document.getElementById('element_within_div'); var topPos = myElement.offsetTop; The variable topPos is now set to the distance between the top of the scrolling div and the element you wish to have visible (in pixels). Now we tell the div to scroll to that position using scrollTop: document.getElementById('scrolling_div').scrollTop = topPos; If you're using the prototype JS framework, you'd do the same thing like this: var posArray = $('element_within_div').positionedOffset(); $('scrolling_div').scrollTop = posArray[1]; Again, this will scroll the div so that the element you wish to see is exactly at the top (or if that's not possible, scrolled as far down as it can so it's visible).
但不是下面这样用: 文中的 divElem 不是想看到的 Elem,而是包含它的 div You would have to find the position of the element in the DIV you want to scroll to, and set the scrollTop property. divElem.scrollTop = 0; Update: Sample code to move up or down function move_up() { document.getElementById('divElem').scrollTop += 10; }
function move_down() { document.getElementById('divElem').scrollTop -= 10; } source
select HTML element#
Queryselector And Queryselectorall Vs Getelementsbyclassname And Getelementbyid
2019-11-14 04:22:44 简单说 getElementsByClassName 根据页面变化实时更新 querySelectorAll 不根据页面变化更新(因此应该占用资源更少?)
#
对应 id
.
对应 class
Also []
is a selector
About the differences, there is an important one in the results between querySelectorAll and getElementsByClassName: the return value is different. querySelectorAll will return a static collection, while getElementsByClassName returns a live collection. This could lead to confusion if you store the results in a variable for later use:
A variable generated with querySelectorAll will contain the elements that fulfilled the selector at the moment the method was called. A variable generated with getElementsByClassName will contain the elements that fulfilled the selector when it is used (that may be different from the moment the method was called). For example, notice how even if you haven't reassigned the variables aux1 and aux2, they contain different values after updating the classes:
// storing all the elements with class "blue" using the two methods var aux1 = document.querySelectorAll(".blue"); var aux2 = document.getElementsByClassName("blue");
// write the number of elements in each array (values match) console.log("Number of elements with querySelectorAll = " + aux1.length); console.log("Number of elements with getElementsByClassName = " + aux2.length);
// change one element's class to "blue" document.getElementById("div1").className = "blue";
// write the number of elements in each array (values differ) console.log("Number of elements with querySelectorAll = " + aux1.length); console.log("Number of elements with getElementsByClassName = " + aux2.length); .red { color:red; } .green { color:green; } .blue { color:blue; }
1 2 3 |
|
来源:https://stackoverflow.com/a/39213298
e.g. document.querySelector("#demo")
Operators 运算符#
- ^: XOR 异或
1 2 |
|
<
a<x<b
的运算顺序是a<x ? true : false
然后再将 true/false 和 b 比较大小。
Events#
Target & Currenttarget#
They are different. 2019-11-12 21:11:57 按钮点击的时间发生时候,传递的参数不同,容易搞混。
Arrow Function#
- In case of returning an object, to distinguish from code block, use bracket
()
argin => ({foo: bar})
- 不绑定 this
- 不绑定 arguments
- 箭头函数没有 prototype 属性。
- 没有 yield 关键字。
- Should be prefered than normal function
Function Arguments#
func(a=1,b)
is same as func(a=1,b=undefined)
输入一个数据时 a 的值会被覆盖,b 未赋值。可省略参数只能写在后面。(实际上都可以省略,调用的时候显示未赋值而已。)
剩余参数(...restArgs)
- restArgs 包含所有实参 restArgs 是真数组(因此有.length 方法) restArgs 没有附加属性(如 callee)
Variable types#
- ==的强制转换:
1 2 3 4 5 6 |
|
- force conversion of If If 后加任何非空变量都会执行。因此如果想判断 array 是否为空,最好直接 if (array.length) 来源:https://stackoverflow.com/questions/24403732/check-if-array-is-empty-or-does-not-exist-js If([])会执行 If(![])不会执行 If({})会执行,判断是否为空可以 if(Object.keys({})),不会执行 If(!{})不会执行 If([]==true)不会执行。 参考:https://blog.csdn.net/bnk_along/article/details/89521582
code review#
oneline code#
http://www.p01.org/256b_mars_canvas/ http://ourjs.com/detail/54be0a98232227083e000012 https://gist.github.com/addyosmani/fd3999ea7fce242756b1 (CSS Layout Debugger)
1 2 3 4 5 6 7 8 |
|
https://github.com/rapidhere/fpjs //(convert JS to one line) https://github.com/csvoss/onelinerizer //(convert python to one line) http://www.jsfuck.com/ //(convert JS to chars)
eg:
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
explain: JS variable type conversion https://www.cnblogs.com/lvdabao/p/4280518.html
API#
Genaral#
response.header#
Header contains a hidden (invisible in console) JSON https://developer.mozilla.org/zh-CN/docs/Web/API/Headers To check the entries, use
1 2 3 |
|
https://developer.mozilla.org/zh-CN/docs/Web/API/Headers/entries
response.body#
when fetching some API, like WordsAPI
+ fetch. should write an async function to help the function works correctly.
after the fetch
, apply .json()
to the response
- https://stackoverflow.com/questions/45366789/trying-to-access-response-data-using-fetch
- https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch
- https://developer.mozilla.org/en-US/docs/Web/API/Body/json
Web API#
setTimeout#
可以给 setTimeout 加一个终止:clearTimeout
1 2 |
|
source 2019-11-20 08:13:23
Date Object#
1 2 3 4 5 6 7 8 |
|
webpack file import (and export)#
import:
https://webpack.js.org/api/module-methods/
there are several import
-s in JS..
require : old staff
- webpack can resolve json, js file with native support.
1 2 3 4 |
|
- function(string path):Promise
- can be called dynamically on runtime.
- Magic Comments
P.S. export: I use FileSaver.js
from GitHub
Web Crypto API#
Key -> plain text : exportKey
plain text -> Key : importKey
Key -> encrypted text : wrapKey
encrypted text -> Key : unwrapKey
generateKey
& exportKey
#
Promise Ver.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
async Ver.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
|
Code style#
-
focus on the logic / readability, not the performance. Idea from:
Array.push and Array.length appending performance: They are different across the browsers. This is the answer persuaded me to not dwell on this: https://coderwall.com/p/kvzbpa/don-t-use-array-foreach-use-for-instead
- Label statement can be used for specify a loop for
continue
andbreak
- The simplest loop in JS i found is
for
/while
. For the clarity, i choosefor
.
- 函数命名 https://www.cnblogs.com/dolphin0520/p/10567879.html
- below from https://juejin.im/post/6844903840030932999
===
is faster than==
Array.isArray(obj); // its a new Array method
instead ofarr instanceof Array;
myArray.length = 0;
myArray will be equal to [].myArray.length = 4;
first 4 elements.
delete items[3];
is same asitem[3] = undefined
. shoulditems.splice(3,1);
for(var i = 0, len = arrayNumbers.length; i < len; i++) {}
.len
只会计算一次。
- UglifyJS (JS compressor)
habit#
-
ALWAYS use
[]
Array constructor. https://coderwall.com/p/h4xm0w/why-never-use-new-array-in-javascript (one exception: to allocate memory)Array.forEach
is about 95% slower than for() in for each for Arrays in JavaScript.So, don't use: I completely disagree with this & please allow to explain why: Using for loops is easy enough sure, in most cases.. but your overlooking the entire point of map,forEach
, filter, reduce, find,findIndex
, etc... These make use of functional paradigms, and these paradigms exist for a reason. Functional programming is all about focusing not on how to solve problems and instead, shifts your focus to what to solve. Beyond that, anyone who is worried about performance at this level can go back after they've built their app and measure the app's performance and decide where to optimize (and I will bet you will find most of your optimizations will not be refactoring map, filter, or reduce). Using for loops is like going backwards, not to mention thatforEach
is slow because it is modifying/mutating the original array, whereas .map() returns a new array, is much faster, and without the side effect of mutating the original array. There are fewer and fewer cases where a for loop is viable. Currently, the best use case would be for something like iterating an async generator function using the new for-await-of syntax. Which is super cool. My point is that javascript gives us first class functions and in combination with it's (sorta) functional paradigms can produce: more readable code, better tooling, composition and patterns like higher order functions and currying, beautiful immutability, and many other wins such as referential transparency with pure functions - which reduce side effects and can increase run time, especially if memorized etc... Although I say "sorta" as obviously you're going to need functions with side effects to make API calls, or logs, or write i/o (any function that has I/O). Regardless, I hate to say that I think you're giving bad advice here. Sure, everyone should know how to use all the original loops in javascript and use them well, but using a for loop versus map or evenforEach
(if you just have to mutate that existing array) is going the wrong direction.In short, My object is not to enhance the performance of these browsers. As long as it doesn't bother me, I will use the better, modern, comprehensible
.push()
andforEach()
instead of those might have better performancea[a.length]
andfor
.
ev.target.nodeName == "INPUT" && ev.target.type == "text"
decide if is focusing on input box
Debug#
Broswer Error handling#
DOMException object: search tag: err handle
MDN DOMException
says it's legacy, but I find this useful (with a table): dottoro
Functionalities#
(some should be added to user-snippet) like var x = Math.floor(Math.random() * (max - min + 1)) + min;
[...Array(20).keys()]; // genearte 0,...,19
Pure CSS/JS Toast Notification#
Redirect a Webpage#
Web manipulation#
1 2 3 4 5 |
|
HTML elements manipulation:#
new element#
1 2 3 4 |
|
add element#
- to firstChild of page
1 2 |
|
set attribute#
1 |
|
select element#
-
document.querySelector select only one element. (first match) 只选择第一个元素 support multiple querys 可以匹配多个标签 eg.
document.querySelector("h2, h3").style.backgroundColor = "red";
<h3>A h3 element</h3>
><h2>A h2 element</h2>
will only affect theh3
tag
- document.querySelectorAll() apply forEach on the returned array is common.
- document.getElementsByTagName()
HTML iframe element#
cannot access(read) an element directly from iframe. neither with a new var.
解构赋值#
可以用来:
- 忽略某些返回值
- 交换变量
1 2 3 4 5 |
|
Tools#
test frameworks#
Mocha is a JavaScript test framework! Chai is a BDD / TDD assertion library