文章目录
- 基础语法
-
- 对象
- 遍历
- 变量声明
- 异步
- 模块
- BOM与DOM
-
- screen
- window
- navigator
- location
- 节点树
- 事件
- jQuery
-
- 选择器
- 事件
- Nodejs
-
- nvm
- 模块基础
- TypeScript
-
- Interface
- undefined
- React
-
- 文档
- jsx、tsx
- useXXX
基础语法
js中!和!!的区别及用法
ECMAScript 6 入门
对象
JavaScript 对象
js继承之原型继承
每创建一个函数,该函数就会自动带有一个 prototype 属性,该属性是个指针,指向了一个对象,我们称之为 原型对象。原型对象上默认有一个属性 constructor,该属性也是一个指针,指向其相关联的构造函数。通过调用构造函数产生的实例,都有一个内部属性,指向了原型对象。
解释一下上面的话,下图中,我们定义了一个
Test
方法,那么
Test
的类型是一个
function
,可以称这个
Test
为构造函数,这个函数本身有一个属性叫做
prototype
,其指向的对象,就是原型对象,从中可以看出这个原型对象里有两个属性,分别是
constructor
和
__proto__
然后通过调用
new Test()
构造实例,可以看到这个实例对象里有一个
__proto__
的属性,指向的就是
Test
的原型对象
JS中PROTOTYPE属性解释及常用方法
这篇文章更加深入一点
1.3里解释了为什么向构造函数的
prototype
里添加属性会影响后续构建的所有对象,因为当一个对象被创建时,这个构造函数 将会把它的属性prototype赋给新对象的内部属性__proto__。这个__proto__被这个对象用来查找它的属性。 从上面的例子就可以看出
1.6里说:这个区别就是function定义的方法(对象方法)有一个prototype属性,使用new生成的对象就没有这个prototype属性。也就是prototype属性是对象方法或者构造方法的专有属性。 我没懂,可能意思是说(以上面为例),
Test
里有
prototype
属性,而
let t=new Test()
的
t
里只有一个
__proto__
没有
prototype
吧
彻底理解js中this的指向,不必硬背
刚接触通过函数构建对象(对象方法),我的疑惑是,为啥
function Test(val){this.val=val}
就可以用来构建对象了,例如
let t=new Test("1")
,后来一想,这可能就是
this
的功劳,在上面这篇博客里的**构造函数版this:**的讲解可以看到
JavaScript中call,apply,bind方法的总结。
遍历
JS里的for…in和for…of的用法
变量声明
JavaScript 变量提升
函数的作用域是什么?js 的作用域有几种?
函数作用域和块作用域
理解es6中的暂时性死区
当程序的控制流程在新的作用域(module, function或block作用域)进行实例化时,在此作用域中的用let/const声明的变量会先在作用域中被创建出来,但因此时还未进行词法绑定,也就是对声明语句进行求值运算,所以是不能被访问的,访问就会抛出错误。
前端面试题:JS中的let和var的区别
前面提到了var使用的是函数作用域以及变量提升,那个
f
函数里打印出来的第一个
undifine
就是变量提升的结果,在
f
函数里的作用域,程序构建了一个新的函数作用域,然后发现这个作用域里有一个
var
定义了变量,与
let
类似,这个
var
的变量就会被绑定到这个作用域里并且其声明会被提升到前面去,但此时没有进行词法绑定(求值运算或赋值),但
var
仍可以被访问。
f
里的变量只会影响这个函数作用域的,影响不到
f
外面
let 和 const 命令
异步
JavaScript异步机制详解
JavaScript:彻底理解同步、异步和事件循环(Event Loop)
“事件”就是线程之间相互通知的信息载体,通过一个event对象来记录
Promise
function test(resolve, reject) {
if (Math.random() * 2< 1) {
log('call resolve()...');
resolve('200 OK');
} else {
log('call reject()...');
reject('timeout in ' + timeOut + ' seconds.');
}}
var p1 = new Promise(test);
var p2 = p1.then(result=>console.log('成功:' + result));
var p3 = p2.catch(reason=>console.log('失败:' + reason));
可以先简单了解promise的用法,
p1
是个
Promise
对象,就是
test
方法的容器,这个容器会让
test
方法异步执行,并且在
test
内部,
resolve
作为成功时执行的回调方法,而
reject
作为执行失败时的回调方法,并通过
p1.then
的提供
resolve
方法真实实现,通过
p2.catch
提供
reject
方法的真实实现。
使用 Promise
可以详细了解
Promise
对象到底是什么,本质上 Promise 是一个函数返回的对象,我们可以在它上面绑定回调函数,这样我们就不需要在一开始把回调函数作为参数传入这个函数了。并且
可以通过 Promise 的构造器从零开始创建 Promise。这种方式(通过构造器的方式)应当只在封装旧 API 的时候用到。理想状态下,所有的异步函数都已经返回 Promise 了。
也就是说,一般情况下,我们不会手动new一个Promise对象,除非是
setTimeout(fn)
这类的旧API,这个方法是在一点时间后,将fn放入事件循环队列里等待执行。
这个api是通过将方法
fn
作为参数传进
setTimeout
,实现将
fn
注册为回调函数。但是如果
fn
执行失败,外部没办法捕获这个异常,异常会被抛到最上层,这不是我们希望的,这是因为
setTimeout
没提供这个捕获的功能。
function saySomething(s){
throw new Error('有哪里不对了');
console.log("say somting"+s);
}
setTimeout(() => saySomething("10 seconds passed"), 1000);
通过如下方法可以将异常捕获掉,原理是,promise的异步方法其实就仅仅是执行一个
setTimeout
,而resolve方法本身又是promise的回调,虽然其执行的时机会延后个10s,但无论怎样,当执行过程中出现异常的时候,会被catch方法接住
const failureCallback = err=>console.log(err);
const wait = ms => new Promise(resolve => setTimeout(resolve, ms));
wait(1000).then(() => saySomething("10 seconds")).catch(failureCallback);
理解 JavaScript 的 async/await
那么什么是
async
?没有
async
的时候,异步是通过新建
Promise
完成的,而有了
async/await
,可以通过定义并调用
async function
来返回
Promise
对象;
而使用
Promise
注册回调的时候,如果需要级联多个耗时操作的回调(而这往往是因为每个回调又都是一个返回
Promise
的方法),这时就需要反复地
then
。而有了
async/await
,可以通过在
async function
内部使用
await+try catch
语法改写上述每个返回
Promise
的回调,从而实现像写同步方法那样写异步方法。见《async/await 的优势在于处理 then 链》
async 函数
await
Generator 函数的含义与用法
async 函数的含义和用法
模块
JS 之export、export default和module.exports
js中的export、import、export default等导入导出全解
导包时import花括号{}的作用
BOM与DOM
screen
screen描述的是整个屏幕
window
window描述的是整个浏览器窗口的信息
navigator
navigator描述的是浏览器自身所带的信息(例如版本等)
location
节点树
获取节点的属性和子节点
<div id="d1" class="div"> <div id="d2" class="div">text</div> </div>
获取属性和属性的值,但建议还是用nodeName和nodeValue,不容易混淆,因为文档中都是节点
元素节点:
<div class="class" id="d1">123</div>
就是元素节点,获取方式为
document.getElementById("id")
属性节点:
<div> class="class" id="d1">123</div>
里的
class="class"
就是元素节点,获取方式为
document.getElementById("id").attributes['class']
或者
.attributes[0]
内容节点
<div> class="class" id="d1">123</div>
里的
123
就是内容节点,获取方式为
document.getElementById("id").childNodes[0]
需要进一步说明的是,没有明确指定的属性是不会生成属性节点的,例如
<input />
这个元素节点的属性节点是空的,所以要访问其
value
,只能通过
.value
的方法;另外,通过
.
可以获得元素节点的全部非自定义属性的运行时使用的值
例如
<input type="checkbox" checked="checked"/>
,
.checked
返回结果为
true
,并且其结果会随着选中状态的改变而改变;而
.attributes['checked']
返回结果为
checked
,即只能获取html页面(浏览器调试台的element页面)上写的属性的值,当然如果使用了js修改了某个属性(例如name)的值,
.attributes['checked']
也会跟着改变。
innerHTML和innerText的使用和区别
不要用自身的子节点替换另一个子节点,如下所示,本意是将第一个节点替换为第二个节点,但这样的操作会直接导致第一个节点被删除,结果变为
2 3
;而如果将
outerD.replaceChild(children[1],children[0]);
改为
outerD.replaceChild(children[0],children[1]);
,结果会导致第二个节点被删除,结果变为
1 3
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script>
function f() {
let outerD=document.getElementById("outerD");
let children=outerD.children;
outerD.replaceChild(children[1],children[0]);
}
</script>
</head>
<body>
<div id="outerD">
<div id="d1">1</div>
<div id="d2">2</div>
<div id="d3">3</div>
</div>
<button onclick="f()">button</button>
</body>
</html>
为什么呢?个人理解是这样的。对于节点的操作有
appendChild
,
insertBefore
,
replace
等等很多,以
replace(newNode,oldNode)
为例,功能是将
oldNode
节点替换为
newNode
节点,具体操作过程是分步的:即首先将
newNode
节点从其原本所属的父节点上拆下来,然后把
oldNode
替换为
newNode
;如上例,
outerD.replaceChild(children[1],children[0]);
,其中
children[1]
为
d2
,
children[0]
为
d1
,先把
d2
从
outerD
上拆下来,此时
outerD
上只有
d1
和
d3
,随后将
d1
替换成
d2
,此时就剩
d2
和
d3
了。
appendChild
同理,需要将待添加的元素从原来的父节点上拆下来,加到新的节点后面
JavaScript中querySelector()和getElementById()(getXXXByXX)的区别
由于querySelector返回的是静态的,因此在使用template的时候,使用的是query获取template节点,以免破坏template本身
事件
JS事件机制
冒泡与捕获阶段
下面这个键盘敲击事件传入的是
this
,也就是元素节点对象,你会发现当你输入的是
abc
的时候,事件函数获取其
value
为
ab
,也就是说,
onkeypress
事件函数会发生在
input
标签的
value
更新之前;为了修正这个问题,我们可以把
onkeypress
改为
onkeyup
,
onkeyup
的事件函数会发生在
input
标签的
value
更新之后,这也就是说,输入框的更新时机是键盘敲击之后,抬起之前
事件及DOM
事件参考
目前的html规范已经不建议在html标签里直接写
onclick
的属性了,而是建议按dom2的方式书写,但是我觉得这样有点麻烦啊= =,例如,要在页面加载完成后绑定事件方法,以及用
onkeydown="return false"
可以禁止输入,但使用下面的方法如何控制禁止输入呢
function check_name(event) {
console.log(event);//事件本身
console.log(this);//事件触发的元素节点
}
document.getElementById("username").addEventListener("keypress",check_name);
如何禁止输入,找到了一个答案
function check_name(event) {
console.log(event);//事件本身
console.log(this);//事件触发的元素节点
event.returnValue=false;//通过这个属性进行更改
}
或者dom0方式进行时间绑定
document.getElementById("someID").onkeydown=function(event){
console.log(this);//事件触发的元素节点
console.log(event);//事件本身
}
document.getElementById("dom0").onkeydown=null;//注销事件
表单事件
onsubmit
可以阻止表单的提交,如
onsubmit="return f()"
且
f(){return false}
,
onkepress
也可以实现禁止输入
jQuery
选择器
<div id="d1">Hello JQuery</div>
<div >Hello JQuery</div>
可以看到返回的jQuery对象有一个叫
的属性,这个属性的对象就是
div#d1
这个
div
,可以通过
$("#d1")[0]
来获取这个对象,这个对象就是DOM原生的元素节点对象
jQuery里的
this
<script>
$(function(){
$(".b").click(function(){
console.log(this,this.value);//this就是选择器所选择的标签,是一个DOM原生的元素节点对象,
let jQuery_obj = $(this);//用$将元素节点对象转化为jQuery对象
console.log(jQuery_obj.val());//使用jQuery对象的方法
});
});
</script>
<button value=":input" class="b">切换所有的:input</button>
prop
和
attr
的关系类似于从原生DOM的元素节点上通过
.
和通过属性节点获得属性的值。
prop
能获取元素节点的全部非自定义属性的运行时使用的值****,而
attr
只能获取html页面**(浏览器调试台的element页面)上写的属性的值,例如
通过
$("#c").prop("checked")
的结果
true
,其结果会随着选中状态的改变而改变,而
$("#c").attr("checked")
的结果
checked
,选中状态的改变并不会改变
checked
这个属性的值,所以
.attr("checked")
不会跟着变,当然如果使用了js修改了某个属性(例如name)的值,
.attr("name")
也会跟着改变。
事件
jQuery的事件对象不是DOM原生的事件对象,是对其的封装,不过功能基本相同
Nodejs
何为nodejs-和-npm
nodejs就是一个js的运行环境
nvm
npmmirror 中国镜像站
nvm node_mirror https://npmmirror.com/mirrors/node/
nvm npm_mirror https://npmmirror.com/mirrors/npm/
模块基础
Node搜寻模块规则
npm install -g
是全局安装,该包会安装在nodejs目录的node_module下面
如果在一个名字为A的文件夹下面安装依赖库,并且这个依赖库的名字也是A的话,会报错,文件夹名字不能与安装的包的名字相同,这样会导致搜索包时的无限循环
nodejs中package.json和package-lock.json文件的功能分析
Nvm ls-remote结果为N/A的解决方案
在环境变量里加上
export NVM_NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node/
TypeScript
Interface
TypeScript之interface定义对象(二)
ts里的interface更像是pojo
undefined
Type ‘undefined’ is not assignable to type in TypeScript
The “Type ‘undefined’ is not assignable to type” error occurs when a possibly undefined value is assigned to something that expects a different type.To solve the error, use the non-null assertion operator or a type guard to verify the value is of the specific type before the assignment.
React
文档
https://beta.reactjs.org/learn
jsx、tsx
(005)RN开发 js jsx ts tsx的区别
就是Javascript和XML结合的一种格式,一个代码里,即能写js,也能写xml。tsx就是将js升级为ts,带上了类型
useXXX
useXXX都是带来side-effect的内置函数,所谓side-effect指的是副作用,或者更确切我觉得应该叫做侧面影响,如果一个函数多次运行的结果都相同,那么说这个函数没有副作用,但是如果每次运行的结果都不一致,那么就说这个函数有副作用。比如useState就是为了给函数带来一些副作用,从而控制每次的输出。比如说分页请求,第一次渲染某个组件,是按照默认的分页大小请求,用户修改了分页大小,那么重新渲染这个页面的时候,就会导致输出的结果不一样
这块确实建议看官方文档,讲得很好
Synchronizing with Effects
State: A Component’s Memory
轻松学会 React 钩子:以 useEffect() 为例
useEffect 使用指南