天天看点

【JS】积累与发现基础语法BOM与DOMjQueryNodejsTypeScriptReact

文章目录

  • 基础语法
    • 对象
    • 遍历
    • 变量声明
    • 异步
    • 模块
  • 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__

【JS】积累与发现基础语法BOM与DOMjQueryNodejsTypeScriptReact

然后通过调用

new Test()

构造实例,可以看到这个实例对象里有一个

__proto__

的属性,指向的就是

Test

的原型对象

【JS】积累与发现基础语法BOM与DOMjQueryNodejsTypeScriptReact

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,不容易混淆,因为文档中都是节点

【JS】积累与发现基础语法BOM与DOMjQueryNodejsTypeScriptReact

元素节点:

<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>
           
【JS】积累与发现基础语法BOM与DOMjQueryNodejsTypeScriptReact

可以看到返回的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 使用指南

继续阅读