【JS学习笔记】

JS学习笔记

HTML和CSS相关知识点

  1. 什么是选择器?.xxx{} ,#xxx{} ,xxx{}, *xxx{},
  2. HTML中的<body>的JS会在页面加载时被执行<head>的JS会预先加载,但在被调用时才执行
  3. JS中如何获取html元素:document.querySelector('选择器')
  4. html 元素如何插入:containerMovements.insertAdjacentHTML('afterbegin',html) containerMovements.innerHTML

JS小知识点

1. JS 的[ ]

引用表达式,比如
jonas[interest],interest = 'job'可以访问到Jonas对象的job属性
[ ]内还可以是各种加减乘除形式的表达式,比如['day-${2+4}'] : {open:0;close:24}

2. JS的this

表示指向当前对象,注意:在函数中的函数如果有this将会使得其指向undefined,解决方法为用bind(),或者箭头函数,因为箭头函数对象不会被获取到。this 的好处在于,对象被赋值到新变量时,不需要更改内部的名称,只要属性一致就可以复用this.year,进而使用method borrowing

3. the spread operator 和 the rest pattern是相反的

前者将一个变量(arr)形成多个新变量(3,4,5)const newArr = [1,2,...arr];
后者将多个变量(2,3)形成一个新变量(number)const add = function(...number){console.log(number);} add(2,3); add(2,3,4)

4. JS 的短路:

短路||:一真(且非0,非undefined,非空)则真;
短路&&:一假则假,非假则后;
短路??:一真(且非undefined,非空)则真。

运算符返回内容不返回内容
&&第一个falsy value 或 last value
??第一个非null valuenull,undefined

5. JS 的entries:

menu.entries() 数组的一个方法,会列出多个数组,每个数组有两个元素,[0] 是位置,[1]是数组的元素。对象也有这个方法,只是第一个位置不是表示位置的0123,而是key。for(const [i,el] of menu.entries()) {console.log(${i+1}:${el})}

6. 函数的call(obj, arg)方法和bind(obj,arg)方法区别:

一个直接执行函数,一个返回一个函数。

7. JS中可以用下划线

可以帮助理解,不影响输出const price = 345_99 ;console.log(price); >> 34599

8. JS是面向对象的语言,JS不使用类(万物皆对象)。

在JS中,不会创建类,也不会通过类来创建对象,JS创建对象有两种方法①使用Object定义并创建对象的实例Person = new Object();Person.firstname = 'John';或者person = {firstname: 'John'};②使用构造函数来定义对象,prototype来定义方法(所有对象都会至少继承于Object),然后创建新的对象实例const Person = function(name){this name = name;} ;Person.prototype = Object.create(Man.prototype)const person = new Person('John);

9. JS是基于prototype,而不是基于类的

在JS中,几乎所有对象都是Object的实例,都会从Object.prototype继承属性和方法

10. ES6 classes:

是一种②的替代方案,看似类,其实质仍是基于构造函数,“Hide the truth nature of JS, but create a block that we used to.”

11. JS 中的继承:

①用构造函数完成 ⅠPerson.call (this, firstname);Student.prototype = Object.create(Person.prototype);
②用类完成Ⅰsuper(make,speed);class EV extends Car {...}

复制对象

当某对象复制给新对象时,本质是创造了一个变量,该变量指向了原对象的地址,所以改变新对象的属性等于改变原对象的属性。
解决方法:
① 用Object.assign ( )const friend = Object.assign({},me);//me是原对象
②用The Spread operator const newRestaurant = {...restaurant, founder:'Guiseppe'};

闭包Closure和返回函数

在一个函数内部创建另一个函数,内层函数中访问到其外层函数的变量,就会形成闭包.
狭义的Closure通常是作为返回值,外部函数返回内部函数。
A closure makes a function remember all the variables that existed.

const greet = function(greeting){
	return function(name){
				console.log(`${greeting} ${name}`);
	};
};
greet('hello')('Jonas');//调用greet函数

//箭头版
const greetArr = 
greeting => name => console.log(`${greeting} ${name}`);

可以把函数定义在全局,赋值在局部,closure可以让全局访问到该函数

let f;
const g = function(){
	const a = 23;
	f = function(){
		console.log(a);
	};
};
g();//要先调用了g,才能调用f
f();

理解Closure:
本来函数外不能访问函数内的变量,因为作用域的问题;但是此时closure机制使得 某函数中能够访问该函数中的函数的变量。
按道理内层函数中的变量应该只能在该内层函数中使用,但是该变量居然可以在外层函数被访问,这就是closure的魔力。

Array的方法

来源:Jonas课程

Intersection Observer API

用于监听目标元素的可见部分(比例),当超过了threshold时,会执行指定的回调函数

const options = {
  root: document.querySelector("#root"), //根元素
  rootMargin: "0px", //传值形式类似于css的margin 传一个值则四个边都为0
  threshold: 0, //触发条件 表示目标元素刚进入根元素时触发
};
const callback = function(){console.log('执行回调函数内容')}

//IntersectionObserver对象
const observer = new IntersectionObserver(callback, options);
const target = document.querySelector("#target"); //目标元素
observer.observe(target); //开始监听该目标元素

失去prototype chain

如果将数据存储在浏览器的localStorage,再次调取会失去prototype chain
上方是重新加载网页时获取的localStorage里的running对象,下方是在运行中输出的running对象

JS的异步性

其中,micro-tasks queue 中的promise可以插队

异步执行的东西(如加载图片,请求数据)都会在浏览器环境下执行,并放入callback queue和microtasks queue中,而不会在主线程call stack中执行,所以加载时也不会拖慢整个代码执行。
异步性使得程序运行不完全按照代码的书写顺序。
分析代码执行顺序
正确顺序
timer是放在callback queue,promise是放在microtasks queue

不管promise有多长,promise(microtasks queue)可以优先于timer(callback queue)

创建promise,理解promise

在这里插入图片描述
resolve函数和reject函数返回的分别是res和err

创建promise两种方式:①new Promise()②用Promisify

promise 详解和手动实现promise:promise 详解和手动实现promise

promise传入两个参数(分别为resolve函数和reject函数),
如果promise状态为fulfilled则执行resolve函数,
如果promise状态为rejected则执行reject函数;

通过then方法可以对 Promise 中的resolve进行处理,
then方法(catch方法同理)的返回值是一个 Promise 实例,所以then可以连用;
then方法(catch方法同理)的返回值也可以是一个普通值,则该值作为一个新的promise的resolve()的返回值。

可以将现成数据转化为一个promise
可以直接promise.resolve(),相当于new promise ( resolve => { resolve() } )

promise 方法

then ()
catch ()
finally ()

all ([ ]) 创建多个promise

allSettled () 该方法返回的 Promise 实例,会在所有 Promise 实例执行完毕后,状态方可变为fulfilled,并且只会是fulfilled

race ([ ]) 返回第一个返回的promise

any ([ ]) 返回第一个满足的promise,但是忽略reject

Async function

keep running behind the scene, return a promise
在这里插入图片描述
使用await 会返回紧跟着的promise的fulfilled状态下获取的值,相当于直接执行resolve()

ES6 Modules

来源:Jonas课程ppt
ES6 Module 也是以js文件存储,但是与一般的script.js具有差异(具体看右表)
JS的module和python的包类似,与python的异同点如下:

同:

  1. 通过import导入依赖模块

异:

  1. JS的模块要在html中指明文件类型是module<script type='module'></script>
  2. 使用包中的变量或方法需要export,而python直接pd.xxx
  3. JS的export default:
    包内
    包外调用
    export default 后面的东西可以被命名为add或其他名称,在导入时跟在import后面。
  4. 如果要获取包里所有变量,则使用import * as 包名 from ‘包名路径’,这样可以像python一样使用包
  5. 对JS来说,import导入不是普通的获取,而是建立一个连接,对包内的变量的改动将会影响包内本身变量的值。

NPM:Node Package Manager

在NPM出现以前,我们调用包都是通过<script>,但是总是需要手动在html中更改版本或者包名;

安装:nodejs.org/en/ 网址
查询:终端输入npm -v

每一个需要使用npm的项目,都要先初始化npm:终端输入npm init
于是可以定义各种文件属性,直接回车表示默认值
终端截图
npm 安装leaflet:npm install leaflet
在这里插入图片描述