网站地址:www.digitalocean.com/community/t…
第一篇:How To Use the JavaScript Developer Console
- Cmd + option + J 打开chome浏览器控制台
- let today = new Date(); 可以获取系统当前时间
- 控制台直接进行dom操作(更改是临时的):
- 修改页面内容:
- document.body.innerHTML = “<h1>whatever</h1>”
- 元素样式修改(相当于body元素的inline style):
- document.body.style.backgroundColor = “lightblue”
- 添加段落元素标签:
-
- let p = document.createElement(“P”)
-
- let t = document.createTextNode(“Paragraph text.”)
-
- p.appendChild(t)
-
- document.body.appendChild(p)
-
- 修改页面内容:
- 更多关于Network Tab的东西:developer.chrome.com/docs/devtoo…
- 更多关于Responsive Design的东西:developer.chrome.com/docs/devtoo…
第二篇:How To Add JavaScript to HTML
- <script>元素标签中可以放置JS代码,取决于你想这些code snippets在什么时候加载,可以分别放在<head>或<body>中
- 放head中,浏览器在剩余页面加载前运行JS代码
- 防body中,。。。加载后运行。。。
- 当然为了分离html和js以及css内容,一般都是放在独立文件中再引入,通过:
- <link rel="stylesheet" href="css/style.css" />
- <script src="js/script.js" />
第三篇:How To Write Your First JavaScript Program
- let name = prompt(“greeting msg”); 可以获取用户的输入,相当于python的input
第六篇:Understanding Data Types in JavaScript
- JS只有一种数字类型number(无论是整数类型还是浮点类型),所以let num1 = 93和let num2 = 93.00是一样的
- JS中有正/负无穷(除以零)和NaN(不合法类型,不同于undefined)
- JS中如果string可以被解析为数字,那么可以进行运算:let y = 20 / “5”
- JS中object并不是hashMap,只是一系列的键值对,当然实现方式可以是hashMap,object的key只能是string(会在添加kv pair时被强转)
第七篇:How To Work with Strings in JavaScript
- JS中`xxx ${variable} yyy`可以被用于在字符串中加变量(template literals)
- String literal vs. String value的区别,前者是源码中的,后者是显示输出
- 为了使代码更易读,多行的string文本,一般也使用template literal(即``)
第八章:How To Index, Split, and Manipulate Strings in JavaScript
- String primitives vs. String objects:后者指new String(“ddd”)出来的字符串,用JS中的typeof来查看各自类型的话,会发现前者是string,后者是object;一般情况下都是使用原生string,因为又一些内置的特性更方便
- JS中String相关的函数:charAt,indexOf,lastIndexOf,slice,toUpperCase,split,trim,replace,toString,includes等内置方法(其中replace中还可以使用正则表达式进行匹配,更多可看regexr.com/)
第九章:How To Convert Data Types in JavaScript
- JS中可以通过String(),Number(),Boolean()进行强转type coercion
第十章:Understanding Variables, Scope, and Hoisting in JavaScript
- JS规范:ECMAScript 2015(ES6):262.ecma-international.org/6.0/
- var, let, const的不同点:
- JS中的Hoisting(变量提升):
- 两个结果都是undefined
- 两个结果都是undefined
- JS中const变量一般都是全大写
第十二章:Understanding Comparison and Logical Operators in JavaScript
- JS中的==表示相等(equality),但3==‘3’也是真,===表示严格相等(identity),需要包括类型在内也相等
第十三章:Understanding Arrays in JavaScript
- 跳过index对数组进行赋值:比如0-4位置都有内容,但是现在在6位置赋值,那么5位置就会有一个undefined
- JS中数组常见的函数:push,unshift,pop,shift,splice,slice,concat,reverse,fill,sort,join,indexOf,lastIndexOf等
- push, unshift是 尾/前 添加元素,pop, shift是 尾/前 移除元素
- splice可以最多接收3个参数
- sort中使用的比较函数cmp可以定义在外边
- Join的默认delimiter是逗号,并且其中没有空格
- JS中的数组或string等iterable对象的新遍历方式:
for … of,比如 for (let a of arr) {};(另外for (let [index, a] of arr.entries()) {}还可以把下标也带上)forEach+ 箭头函数,比如 arr.forEach(a => { doSthWithItem(a) })- 函数式编程:map, reduce, filter, find, findIndex…
第十四章:How To Use Array Methods in JavaScript: Mutator Methods
- 测试一个object是否是Array:
Array.isArray(obj)
第十七章:Understanding Objects in JavaScript
delete关键字可以删除一个JS中object对象的一个特性property,比如delete obj.prop,如果存在prop,返回true- 遍历JS中object特性:
for … in,比如 for (key in obj) {} Object.keys(obj)会返回一个对象的key的数组
第十八章:Understanding Date and Time in JavaScript
- JS中new一个
Date类,格式是:周几 月 日 年 时:分:秒 时区;date.getTime()获得一个Unix时间(另外还有getFullYear, getMilliseconds等,另外除了get方法还有set方法);当然new Date的时候也可以传入多参数
第十九章:Understanding Events in JavaScript
- 给element分配event的三种方式:
- Inline event handlers(一般不推荐使用)
- 比如:<button onclick="changeText()">Click me</button>,然后在changeText函数中写上:
const p = document.querySelector(‘p’); p.textContent = “something…” - Event handler properties(即在JS代码中给元素设置event这一property特性而非在直接在HTML中)
const button = document.querySelector('button'); button.onclick = changeText; - Event listeners(优点:可以在同一个element上设置多个event)
button.addEventListener('click', changeText);- 第二个参数可以设置成匿名函数() => {}
- 另外可以removeEventListener()
- Inline event handlers(一般不推荐使用)
- 常用的事件:
- 鼠标事件:
dblclick, mouseenter, mouseleave, mousemove(其中mousemove指鼠标在元素内部每次移动的时候) - 表格事件:
submit, focus, blur - 键盘事件:
keydown, keyup, keypress(第三个指长按),keydown和keypress的区别在于前者会响应每一个key,而后者会忽略不产生字符的key(比如shift, alt, delete键)- 键盘事件有特殊的特性可以接入单个key,如果一个参数event被传入一个event listener中,我们就能获得刚发生的event的更多信息。比如在键盘这里,可以获取键的key(e.g. a)和code(e.g. KeyA)两个property),比如:
document.addEventListener('keydown', event => { console.log('key: ' + event.key); console.log('code: ' + event.code); });
- 键盘事件有特殊的特性可以接入单个key,如果一个参数event被传入一个event listener中,我们就能获得刚发生的event的更多信息。比如在键盘这里,可以获取键的key(e.g. a)和code(e.g. KeyA)两个property),比如:
- 另外event的另一个property,
target经常被使用,它指向事件的发生者element
- 鼠标事件:
第二十章:How To Work with JSON in JavaScript
- JSON的其他信息:
- 入门介绍:www.digitalocean.com/community/t…
- JSON在线格式化工具:www.jsonformatter-online.com/
- JSON和JS object的区别:
- JS object中的keys是不放在quotes里面的
- JS object中可以有function作为value
- JSON可以被任何编程语言使用,因为它是text-based
- 处理JSON的函数:
JSON.stringify(),JSON.parse()
第二十二章:How To Use the Switch Statement in JavaScript
- JS中存在
switch range,即case中可以写一个区间,比如:case grade >= 90: xxx; break;
第二十五章:How To Define Functions in JavaScript
- 函数表达式function expression,比如:const sum = function(x, y) {…}
- 当箭头函数中函数主题只有一句返回语句时,可以简写,比如:const square = x => xx; (原本是 const square = (x) => { return xx; })
第二十六章:Understanding Prototypes and Inheritance in JavaScript
- JS是基于原型的语言(prototype-based, meaning object properties and methods can be shared through generalised objects that have the ability to be cloned and extended.),意味着它不同于类继承的其他语言,是prototypical inheritance的
- JS中每一个obj都有一个内部特性
[[Prototype]],这个特性无法在代码中被直接使用,需要使用Object.getPrototypeOf方法获取);prototype将两个或者多个object给联系起来 - 有些浏览器可以通过
__proto__来查看当前obj是基于哪一个object的(但是一般还是最好使用getPrototypeOf),比如:let y = []; // method1 y.__proto__.__proto__ === Object.prototype; // method2 Array.prototype.isPrototypeOf(y); // method3 y instanceof Array - 自定义构造函数可以通过new的方式,比如:
function Hero(name, level) {…} let hero1 = new Hero(‘name’, 1) // Add method to the Eg prototype Hero.prototype.greet = function () {…} - 使用
call方法复制一个构造函数中的所有properties到另一个构造函数中,比如:function Warrior(name, level, weapon) { Hero.call(this, name, level); this.weapon = weapon; }- 但call并不会把prototype properties和methods也都复制过来,需要使用
Object.setPrototypeOf(Warrior.prototype, Hero.prototype);来复制
- 但call并不会把prototype properties和methods也都复制过来,需要使用
- 全部代码块:
// 通过ES6之前默认构造函数的方式 // Initialize constructor functions function Hero(name, level) { this.name = name; this.level = level; } function Warrior(name, level, weapon) { Hero.call(this, name, level); this.weapon = weapon; } // Link prototypes and add prototype methods Object.setPrototypeOf(Warrior.prototype, Hero.prototype); Hero.prototype.greet = function () { return `${this.name} says hello.`; } Warrior.prototype.attack = function () { return `${this.name} attacks with the ${this.weapon}.`; } // Initialize individual character instances const hero1 = new Warrior('Bjorn', 1, 'axe'); hero1.attack(); hero1.greet();- JS中的Class语法源自ES6,其实本质上只是一种语法糖,底层仍使用函数
// 通过ES6新加入的class语法的方式 // Initializing a class class Hero { constructor(name, level) { this.name = name; this.level = level; } // Adding a method to the constructor greet() { return `${this.name} says hello.`; } } // Creating a new class from the parent class Mage extends Hero { constructor(name, level, spell) { // Chain constructor with super super(name, level); // Add a new property this.spell = spell; } }
第二十七章:Understanding Classes in JavaScript
- JS中的Class语法源自ES6,其实本质上只是一种语法糖,底层仍使用JS原生的函数作为实现方式
第二十八章:How To Use Object Methods in JavaScript
- 一些常用的缩写或者技术词汇:www.digitalocean.com/community/t…
- 常用的内置object methods对象方法:Object.create(), Object.keys(), Object.values(), Object.entries(), Object.assign(), Object.freeze(), Object.seal(), Object.getPrototypeOf(), Object.setPrototypeOf()
第二十九章:Understanding This, Bind, Call, and Apply in JavaScript
- JS中,this有四种隐式(
Implicit Context)指代的东西,区分于应用场景:- the global context 全局的上下文
- 在浏览器中时,全局对象就是window;Node.js中则是global
- 为了规避很多JS的sloppy问题,比如this的指向问题(作用域),有时可以使用strict mode编写JS代码(即
use strict),详见:developer.mozilla.org/en-US/docs/…
- As a method within an object 作为对象内部的一个方法
- 在对象内部时,this指向离当前this最近的一层object
- As a constructor on a function or class 作为一个函数或类的构造器
- 当使用关键字new进行新对象创建时,this指向新的对象实例
- As a DOM event handler 作为一个文件对象模型的事件处理器
- 在添加event监听时,那个this指向当前发生事件的element(即
event.currentTarget或event.target)
- 在添加event监听时,那个this指向当前发生事件的element(即
- the global context 全局的上下文
- JS中,this的显式上下文(
Explicit Context),通过call, apply, bind- Call和apply除了接受额外参数时,后者使用列表不同外,其他都类似。它们的作用主要是将一个调用函数的this联系到一个给定的上下文,比如:
const book = { title: 'Brave New World', author: 'Aldous Huxley', } function summary() { console.log(`${this.title} was written by ${this.author}.`) } summary.call(book) // or: summary.apply(book) - 不同于call和apply的一次性使用(调用时生效,原函数不变),bind可以用于创建一个与给定context永久绑定的新函数;重新绑定别的context是不行的
const braveNewWorldSummary = summary.bind(book) braveNewWorldSummary() - 箭头函数是没有自己的this绑定的,而是指向箭头函数之外的一层context
react等框架中箭头函数的常见的用法const whoAmI = { name: 'Leslie Knope', regularFunction: function() { console.log(this.name) }, arrowFunction: () => { console.log(this.name) }, } whoAmI.regularFunction() // "Leslie Knope" whoAmI.arrowFunction() // undefinedconst button = document.createElement('button') button.textContent = 'Click me' document.body.append(button) class Display { constructor() { this.buttonText = 'New text' // 这里如果是写 function(event) {...},那么里面的this // 就是指发生event的element,而用箭头函数的话,this的指 // 向就是outer context,在这里就是外层的class的context button.addEventListener('click', event => { event.target.textContent = this.buttonText }) } } new Display()
- Call和apply除了接受额外参数时,后者使用列表不同外,其他都类似。它们的作用主要是将一个调用函数的this联系到一个给定的上下文,比如:
第三十章:Understanding Map and Set Objects in JavaScript
- JS中Map的建立通过new,Map变量会有
set, get, has, delete, clear等函数 - 可以通过函数
Objects.entries()和Object.fromEntries()来进行对象object和映射Map的相互转化,比如:const map = new Map(Object.entries(obj)); const obj = Object.fromEntries(map) - 可以使用
Array.from(map)将一个映射对象转化为数组对象 - Map中key可以不同的语言原始类型primitives,比如map.set(‘1’, ‘String one’)和map.set(1, ‘Number one’)是不同的(Set中是add)
- 在object中,由于对象中将所有key都转换成了string类型,所以诸如const obj = { 1: ‘One’ },其中obj[1] === obj[‘1’]是返回true的;但是在Map中,object是可以不转化为string直接作为key的
- 注意当使用object或者array作为key时,Map实际上时使用这些对象的引用reference来作为对比,而非是对象的字面值,比如:{} === {}是返回false的,因为它们并不是同一个对象,所以诸如map.set({}, ‘One’}; map.set({}, ‘Two’)实际上设置了两个pair
- Map的遍历:
Map.prototype.forEach((value, key, map) = () => {})- 对比于Array.prototype.forEach((item, index, array) = () => {})
map.forEach((value, key) => {…}注意这个value在前for (let [key, value] of map) {…}
第三十一章:Understanding Generators in JavaScript
- 生成器函数定义是带星的,比如:function* generatorFunc() {},且该函数会返回一个生成器对象
generator function不可以通过new关键字构建,也不可以和arrow function联用- 生成器函数返回的迭代器有一个
next函数,next函数会返回一个value和done - 用for…of或spread操作符时,只会遍历yield的返回,return不会打印
- 生成器函数可以通过return和throw方法马上中断,比如:
- generator.return()
- generator.throw(new Error())
- yield* 可以用作更好的组织代码结构
- generators可以用于代替async/await,但一般还是用async/await吧
第三十三章:Understanding Destructuring, Rest Parameters, and Spread Syntax in JavaScript
- Spread语法是
shallow copy浅拷贝的,嵌套的对象使用spread时只复制引用 - Spread用于字符串转字符数组很有用,比如:
const string = ‘hello’; const stringArray = […string]; // [“h”, “e”, “l”, “l”, “o”]
第三十四章:Understanding Template Literals in JavaScript
- 创建HTML元素的时候可以使用template interpolation + trim的方式,比如:
const menuItem = (url, link) => ` <li> <a href="${url}">${link}</a> </li> `.trim() menuItem('https://google.com', 'Google') - taged template literals (i.e. template tags)
function tag(strings, ...expressions) { console.log(strings) console.log(expressions) } const string = tag`This is a string with ${true} and ${false} and ${100} interpolated inside.` // ["This is a string with ", " and ", " and ", " interpolated inside." // [true, false, 100]
第三十五章:Understanding Arrow Functions in JavaScript
- arrow functions do not have their own this binding or prototype and cannot be used as a constructor. 箭头函数没有自己的prototype和binding,不能作为构造器使用
- Lexical this:箭头函数中的this的值取决于其所处的作用域(即the lexical environment,或者说
lexical scope指当一个变量定义在你当前的作用域外部时,可以直接的在你当前所在的作用域里调用而无需作为参数传入)。也是因为这个原因,箭头函数适合用作行参函数,而不适合用作对象object的直接方法method - 创建一个对象object是不会定义一个lexical scope的,所以在object内部定义arrow函数作为Method,箭头函数中的this就不会指向当前的object。所以一般都是用传统函数定义作为method
- 箭头函数的异样语法:
- 函数体内返回一个object作为返回值时,需要加(),否则{}会被看作是函数体,比如:
const sum = (a, b) => ({result: a + b}) sum(1, 2)
第三十六章:Understanding the Event Loop, Callbacks, Promises, and Async/Await in JavaScript
- 浏览器环境下的JS的异步特性的许多概念和后端Node.js的大同小异,可以参考:www.digitalocean.com/community/t…
- 浏览器环境下使用
event loop机制来处理并发,因为JS只能一次执行一行代码,它需要event loop这个机制通过call stack或queue的手段来达到何时执行特定哪一行的代码的要求 - Queue是在call stack为空的时候被检查的,如果此时Q中有等待的消息,把该条msg加入到stack,然后开始执行,执行完毕后从stack中移出。比如setTimeout(() => {}, 0)这个函数,第二个时间参数的设置其实是指将该条msg放入q中的时间,而非事实的该条msg的执行时间
- 因为使用callback时的嵌套(本质上是使用setTimeout来达成异步编码)会导致
pyramid of doom或者叫callback hell,让代码的维护变得困难,也不利于阅读。因此ES6中引入了promises机制,但是一些开发者更喜欢使用同步的方式去编写异步的代码,所以ES7又引入了async/await机制 - promise机制
- promise初始化
// Initialize a promise const promise = new Promise((resolve, reject) => {})- 一个promise可以有三种可能状态:
pending,fulfilled,rejected,后两者表示promise已经被解决
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve('Resolving an asynchronous request!'), 2000) }) // Log the result promise.then((response) => { console.log(response) })- promise还可以被链接起来
// Chain a promise promise .then((firstResponse) => { // Return a new value for the next then return firstResponse + ' And chaining!' }) .then((secondResponse) => { console.log(secondResponse) })- 错误处理:
function getUsers(onSuccess) { return new Promise((resolve, reject) => { setTimeout(() => { // Handle resolve and reject in the asynchronous API if (onSuccess) { resolve([ {id: 1, name: 'Jerry'}, {id: 2, name: 'Elaine'}, {id: 3, name: 'George'}, ]) } else { reject('Failed to fetch data!') } }, 1000) }) } // then()处理resolve,catch()处理reject getUsers(false) .then((response) => { console.log(response) }) .catch((error) => { console.error(error) })- Fetch API with promises
// Fetch a user from the GitHub API fetch('https://api.github.com/users/octocat') .then((response) => { return response.json() }) .then((data) => { console.log(data) }) .catch((error) => { console.error(error) }) - aync/await机制 + try catch
// Handle fetch with async/await async function getUser() { const response = await fetch('https://api.github.com/users/octocat') const data = await response.json() console.log(data) } // Execute async function getUser()
第三十七章:Understanding Modules and Import and Export Statements in JavaScript
- Modules和JS普通script脚本的区别:
- Modules不会往global作用域里添加任何东西
- Modules总是在strict mode之下的
- 多次加载同一个Module是无效的,因为Module只加载一次
- Modules需要在服务器环境下(因为CORS策略)
<script type="module" src="functions.js"></script> <script type="module" src="script.js"></script>