javaScript知识点小记

241 阅读17分钟

​ --209/7/25 素衣

数据类型

基础数据类型:数字(number),字符串(string),布尔值(boolean),underfined, null,symbol,BigInt。

引用数据类型:对象(Object)。

Number

string

属性

length 字符串长度

constructor 构造函数

_ proto_ String.prototype 型对象,可向对象添加属性或方法

方法 作用
charAt(index) 返回指定位置的字符
charCodeAt(index) 返回指定位置字符的unicode编码
concat(elements) 链接两个或多个字符串,返回新的字符串
indexOf(str)
lastIndexOf(str)
返回指定字符在字符串首次出现的位置
match(regexp) 查找到正则表达式的匹配
search(regexp) 返回符合正则表达式的位置
slice(start, end) 截取字符串的片段并返回,左闭右开
replace(searchValue, replaceValue) 在字符串中查找匹配的字符串,替换为新的字符串并返回
split(separator) 将字符串按传入字符分割成字符串数组
substr(start, length) 返回从起始位置开始指定数目的字符
substring(start, end) 截取字符串的片段并返回,左闭右开
toLowerCase()
toUpperCase()
toLocalLowerCase()
toLocalUpperCase()
将字符串转换为小/大写
trim()
trimLeft()
trimRight
去掉字符串两边的空白
valueOf()
toString()
返回字符串原始值
localCompare(str) 用特定的顺序来比较两个字符串
String.fromCharCode(codes)
String.fromCodePonit(codes)
将unicode编码转为字符
endsWith(searchSring, postion)
startsWith(searchSring, postion)
判断字符串是否以给定字符串结尾
includes(searchSring, postion) 判断字符串是否包含另一个字符串
repeat(count) 返回新的字符串,包含链接在一起指定数量的副本
String.raw() 用来处理模板字符串
normalize(form) 将字符串正规化
padEnd(targetLength, padString)
padStart(targetLength, padString)
将字符串填充到指定长度

Array

Array.of

Array.of用于将参数依次转化为数组中的一项,然后返回这个新数组,而不管这个参数是数字还是其它。

Array.of(8.0); // [8]
Array(8.0); // [empty × 8]

Array.from

Array.from的设计初衷是快速便捷的基于其他对象创建新数组,准确来说就是从一个类似数组的可迭代对象创建一个新的数组实例,说人话就是,只要一个对象有迭代器,Array.from就能把它变成一个数组(当然,是返回新的数组,不改变原对象)。

var obj = {0: 'a', 1: 'b', 2:'c', length: 3};
Array.from(obj, function(value, index){
  //console.log(value, index, this, arguments.length);
  return value.repeat(3); //必须指定返回值,否则返回undefined
}, obj);
['aaa','bbb','ccc']

Array.isArray

Array.isArray用来判断一个变量是否数组类型。JS的弱类型机制导致判断变量类型是初级前端开发者面试时的必考题,一般我都会将其作为考察候选人第一题,然后基于此展开。在ES5提供该方法之前,我们至少有如下5种方式去判断一个值是否数组:

var a = [];
// 1.基于instanceof
a instanceof Array;
// 2.基于constructor
a.constructor === Array;
// 3.基于Object.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(a);
// 4.基于getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype;
// 5.基于Object.prototype.toString
Object.prototype.toString.apply(a) === '[object Array]';

改变自身的方法

pop、push、reverse、shift、sort、splice、unshift,以及两个ES6新增的方法copyWithin 和 fill。

方法 作用
pop 删除一个数组中的最后的一个元素,并且返回这个元素
push 添加一个或者多个元素到数组末尾,并且返回数组新的长度
reverse 颠倒数组中元素的位置,该方法返回对数组的引用
shift 删除数组的第一个元素,并返回这个元素
sort 数组元素进行排序,并返回这个数组
splice 用新元素替换旧元素的方式来修改数组。
unshift 在数组开始处插入一些元素(就像是栈底插入),并返回数组新的长度
copyWithin 数组内元素之间的替换,即替换元素和被替换元素均是数组内的元素
fill 将数组指定区间内的元素替换为某个值

不会改变自身的方法

concat、join、slice、toString、toLocateString、indexOf、lastIndexOf、未标准的toSource以及ES7新增的方法includes。

方法 作用
concat 将传入的数组或者元素与原数组合并,组成一个新的数组并返回
join 将数组中的所有元素连接成一个字符串并返回
slice 将数组中一部分元素浅复制存入新的数组对象,并且返回这个数组对象
toString 返回数组的字符串形式
toLocaleString
indexOf 用于查找元素在数组中第一次出现时的索引,如果没有,则返回-1
lastIndexOf 用于查找元素在数组中最后一次出现时的索引,如果没有,则返回-1
includes 判断当前数组是否包含某个指定的值,如果是,则返回 true,否则返回 false
toSource 返回数组的源代码(目前fireFox实现)

遍历方法

forEach、every、some、filter、map、reduce、reduceRight 以及ES6新增的方法entries、find、findIndex、keys、values

方法 作用
forEach 指定数组的每项元素都执行一次传入的函数,返回值为undefined
every 使用传入的函数测试所有元素,只要其中有一个函数返回值为 false,那么该方法的结果为 false;如果全部返回 true,那么该方法的结果才为 true
some 测试数组元素时,只要有一个函数返回值为 true,则该方法返回 true,若全部返回 false,则该方法返回 false
filter 使用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。它就好比一个过滤器,筛掉不符合条件的元素
map 遍历数组,使用传入函数处理每个元素,并返回函数的返回值组成的新数组
reduce 数组中的每个值(从左至右) 开始合并,最终为一个值
reduceRight 除了与reduce执行方向相反外,其他完全与其一致
entries 返回一个数组迭代器对象,该对象包含数组中每个索引的键值对
find& 返回数组中第一个满足条件的元素(如果有的话), 如果没有,则返回undefined
findIndex 它返回数组中第一个满足条件的元素的索引(如果有的话)否则返回-1
keys 返回一个数组索引的迭代器
values 返回一个数组迭代器对象,该对象包含数组中每个索引的值
Symbol.iterator(ES6) 同 values 方法功能相同
  • 所有插入元素的方法, 比如 push、unshift,一律返回数组新的长度;
  • 所有删除元素的方法,比如 pop、shift、splice 一律返回删除的元素,或者返回删除的多个元素组成的数组;
  • 部分遍历方法,比如 forEach、every、some、filter、map、find、findIndex,它们都包含function(value,index,array){}thisArg 这样两个形参。

实现map方法

Array.prototype.fakeMap = function(fn, context) {
	if(typeof fn !== 'function') {
        throw new TypeError(`${fn} is not a function`);
    }
    let arr = this;
    let temp = [];
    for(let i = 0; i < arr.length; i++) {
        let result = fn.call(context,arr[i], i, arr);
        temp.push(result);
    }
    return temp;
}

实现filter方法

Array.prototype.fakeFilter = function(fn, context) {
    if(typeof fn !== 'function') {
        throw new TypeError(`${fn} is not a function`);
    }
    let arr = this;
    let temp = [];
    for(let i = 0; i < arr.length; i++) {
        let result = fn.call(context, arr[i], i, arr);
        if(result) {
            temp.push(result);
        }
    }
    return temp;
}

Object

Object.defineProperty()

Object.defineProperty(obj, prop, descriptor) // obj 定义属性的对象 // prop 要定义或者修改的名称或属性 // 正在定义或修改属性的描述符

返回值

传递给函数的对象

descriptor

value:属性的值(不用多说了)

writable:如果为false,属性的值就不能被重写,只能为只读。(默认:false)

configurable:总开关,一旦为false,就不能再设置他的(value,writable,configurable)(默认:false)

enumerable:是否能在for...in循环中遍历出来或在Object.keys中列举出来。(默认:false)

get:

set:

使用Object.defineProperty为对象新增属性时,该属性的writable,configurable,enumerable默认为false

设置value等时,不可设置get set。

var obj = {};

obj.a = 1;

Object.defineProperty(obj, "b",
{
    value: 2
});

console.log(Object.getOwnPropertyDescriptor(obj, "a")); // 打印"{value: 1, writable: true, enumerable: true, configurable: true}"
console.log(Object.getOwnPropertyDescriptor(obj, "b")); // 打印"{value: 2, writable: false, enumerable: false, configurable: false}"

MVVM框架双向绑定

function defineReactive(obj, key, value) {
    var dep = new Dep()
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get: function reactiveGetter() {
            if (Dep.target) {
                dep.depend()
            }
            return value
        },
        set: function reactiveSetter(newVal) {
            if (value === newVal) {
                return
            } else {
                value = newVal
                dep.notify()
            }
        }
    })
}

Object.assign()

Object.assign(target,source) 中将sources对象中所有可枚举的属性的值复制到目标的对象中,其会返回目标对象。

 target = Object.assign({}, traget, source);

Object.getOwnPropertyDescriptor(obj,prop)

该方法是用于如果prop属性存在对象obj上,则返回其属性描述符,如果不存在就返回undefined。该属性描述符由下面的属性所组成。

【value】表示属性的值,仅针对数据属性描述符有效

【writable】当且仅当属性的值可以被改变时为true。(仅针对数据属性描述有效)

【configurable】 当且仅当指定对象的属性描述可以被改变或者属性可被删除时,为true。

【enumerable】当且仅当指定对象的属性可以被枚举出时,为 true。

【get】获取该属性的访问器函数(getter)。如果没有访问器, 该值为undefined。

【set】获取该属性的设置器函数(setter)。如果没有设置器,该值为undefined。(仅针对包含访问器或设置器的属性描述有效) 该方法能够在IE8及以上的浏览器上运行。

Object.getOwnPropertyNames(obj)

该方法返回obj上所有自身可枚举和不可枚举的属性(不包括原型链上的属性),如果传入的obj不是数组,则会报错。该方法的兼容IE9及以上的浏览器。

Object.getPrototypeOf(obj)

该方法返回对象的原型对象,如果没有的话,则返回null。需要指出的是,对于函数对象,其返回的并不是显式原型(prototype),而是隐式原型(proto),该方法兼容IE9及以上的浏览器。

Object.is(val1,val2)

该方法是确定两个值是否是相同的值,这个方法与===相比,其会将-0和+0看成不等,并且对于两个NaN的比较,Object.is()会看成是相等的,而===会将0、-0、+0看成相等的,两个NaN看成不等。

Object.is(0,-0)//false
Object.is(-0,-0);//true
Object.is(NaN,0/0); //true
Object.is(5,5/1); //true

Object.preventExtensions()

该方法可以让一个对象永远不能添加新的属性。

Object.seal(obj)

其对一个对象进行密封,并返回被密封的对象,这些对象都是不能够添加属性,不能删除已有属性,以及不能够修改已有属性的可枚举型、可配置型、可写性。

Object.freeze(obj)

该方法将obj对象冻结,其任何属性都是不可以被修改的。

浅冻结

Object.keys(obj)

该方法会返回obj上所有可以进行枚举的属性的字符串数组

Object.values(obj)

该方法会返回obj上所有可以进行枚举的属性的值

getOwnPropertySymbols(obj)

该方法返回obj对象上自身的(非继承的)所有Symbol属性键。

call,apply,bind解析

三个方法都是为了改变this指向问题。

apply,call二者来言,作用完全一样,只是接受参数的方式不太一样

call(this, arg1, arg2)

apply(this, [arg1, arg2])

var arr1 = [12, '12'];
var arr2 = ['b','123'];
Array.prototype.push.call(arr1, ...arr2);
Array.prototype.push.apply(arr1, arr2);
arr1 // [12, "12", "b", "123"]

bind()方法会创建一个新函数

var foo = {x: 3};
var bar = function() {
    console.log(this.x);
}
bar();// undefined
var func = bar.bind(foo);
func();//3

实现apply

Function.prototype.myApply = function(context,args) {
    context = context || window;
    args = args ? args : [];
    const key = Symbol();
    context[key] = this;
     const result = context[key](...args);
     delete context[key];
    return result;
}

实现call

Funtion.prototype.mayCall = function(context, ...args) {
    context = context || window;
    args = args ? args : [];
    const key = Symbol();
    context[key] = this;
    const result = context[key](...args);
    delete context[key];
    return result;
}

实现bind

Function.prototype.myBind = function(context) {
	var self = this;
	var args = Array.prototype.slice.call(arguments, 1); // 接受除第一个参数外的参数,作为传递用
	return function() {
		var bindArgs = Array.prototype.slice.call(arguments);// 接受返回函数的arguments数组
		self.apply(context, args.concat(bindArgs));
	}
}

浏览器

hash与history路由

hash —— 即地址栏 URL 中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:www.abc.com/#/hello,has… 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。

winow.location.hash=1
// https://www.baidu.com/#1

history —— 利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。(需要特定浏览器支持)。

这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。

window.history.pushState(data,title,url);
history.pushState({a:1},'suyi','data=1');
//https://www.baidu.com/data=1
history.state
// {a: 1}

hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 www.abc.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。

history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 www.abc.com/book/id。如果后… /book/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”

HTTP

1、概述

HTTP 全称是 HyperText Transfer Protocal ,即:超文本传输协议,从 1990 年开始就在 WWW 上广泛应用,是现今在 WWW 上应用最多的协议,HTTP 是应用层协议,当你上网浏览网页的时候,浏览器和 web 服务器之间就会通过 HTTP 在 Internet 上进行数据的发送和接收。HTTP 是一个基于请求/响应模式的、无状态的协议。即我们通常所说的 Request/Response

2、特点

  • 支持客户端/服务器模式
  • 简单快速:客户向服务器请求服务时,只需传送请求方法和路径。由于 HTTP 协议简单,使得 HTTP 服务器的程序规模小,因而通信速度很快
  • 灵活:HTTP 允许传输任意类型的数据对象。正在传输的类型由 Content-Type 加以标记
  • 无连接:无连接的含义是限制每次链接只处理一个请求。服务器处理完客户的请求,并收到客户的应答后,即断开链接,采用这种方式可以节省传输时间
  • 无状态:HTTP 协议是无状态协议。无状态是指协议对于事物处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能会导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就比较快

请求方法

方法名 功能
GET 向指定的资源发出“显示”请求,使用 GET 方法应该只用在读取数据上,而不应该用于产生“副作用”的操作中
POST 指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求文本中。这个请求可能会创建新的资源或者修改现有资源,或两者皆有。
PUT 向指定资源位置上传其最新内容
DELETE 请求服务器删除 Request-URI 所标识的资源
OPTIONS 使服务器传回该资源所支持的所有HTTP请求方法。用*来代替资源名称,向 Web 服务器发送 OPTIONS 请求,可以测试服务器功能是否正常运作
HEAD 与 GET 方法一样,都是向服务器发出指定资源的请求,只不过服务器将不传回资源的本文部分,它的好处在于,使用这个方法可以在不必传输全部内容的情况下,就可以获取其中关于该资源的信息(原信息或称元数据)
TRACE 显示服务器收到的请求,主要用于测试或诊断
CONNECT HTTP/1.1 中预留给能够将连接改为通道方式的代理服务器。通常用于 SSL 加密服务器的链接(经由非加密的 HTTP 代理服务器)

请求头

请求和响应常见通用的 Header

名称 作用
Content-Type 请求体/响应体的类型,如:text/plain、application/json
Accept 说明接收的类型,可以多个值,用,(英文逗号)分开
Content-length 请求体/响应体的长度,单位字节
Content-Encoding 请求体/响应体的编码格式,如 gzip、deflate
Accept-Encoding 告知对方我方接受的 Content-Encoding
ETag 给当前资源的标识,和Last-ModifiedIf-None-MatchIf-Modified-Since配合,用于缓存控制
Cache-Control 取值一般为no-cachemax-age=xx,xx为整数,表示资源缓存有效期(秒)

常见的请求 Header

名称 作用
Authorization 用于设置身份认证信息
User-Agent 用户标识,如:OS 和浏览器的类型和版本
If-Modified-Since 值为上一次服务器返回的Last-Modified值,用于确定某个资源是否被更改过,没有更改过就从缓存中读取
If-None-Match 值为上一次服务器返回的 ETag 值,一般会和If-Modified-Since
Cookie 已有的Cookie
Referer 标识请求引用自哪个地址,比如你从页面 A 跳转到页面 B 时,值为页面 A 的地址
Host 请求的主机和端口号

响应状态行

tool.oschina.net/commons?typ…

浏览器输入 URL 地址后发生的事情

浏览器向 DNS 服务器查找输入 URL 对应的 IP 地址。

NS 服务器返回网站的 IP 地址。

浏览器根据 IP 地址与目标 web 服务器在 80 端口上建立 TCP 连接。

浏览器获取请求页面的 HTML 代码。

浏览器在显示窗口内渲染 HTML 。

窗口关闭时,浏览器终止与服务器的连接。

JS事件循环机制

JavaScript 语言的一大特点就是单线程, 事件循环的执行机制: 循环首先从宏任务开始,遇到script,生成执行上下文,开始进入执行栈,可执行代码入栈,依次执行代码,调用完成出栈。 执行过程中遇到上边提到的调度者,会同步执行调度者,由调度者将其负责的任务(回调函数)放到对应的任务队列中,直到主执行栈清空,然后开始执行微任务的任务队列。微任务也清空后,再次从宏任务开始,一直循环这一过程。

同步任务队列

异步任务队列

宏任务(task)

script(整体代码)

setTimeout, setInterval, setImmediate,

I/O

UI rendering ajax请求不属于宏任务,js线程遇到ajax请求,会将请求交给对应的http线程处理,一旦请求返回结果,就会将对应的回调放入宏任务队列,等请求完成执行。

微任务(jobs)

process.nextTick

Promise

Object.observe(已废弃)

MutationObserver(html5新特性)

在 Node 中,会优先清空 next tick queue,即通过process.nextTick 注册的函数,再清空 other queue,常见的如Promise;此外,timers(setTimeout/setInterval) 会优先于 setImmediate 执行,因为前者在 timer 阶段执行,后者在 check 阶段执行。

console.log('script start');

setTimeout(function() {
  console.log('timeout1');
}, 10);

new Promise(resolve => {
    console.log('promise1');
    resolve();
    setTimeout(() => console.log('timeout2'), 10);
}).then(function() {
    console.log('then1')
})

console.log('script end');

// script start
// promise1
// script end
// then1
// timeout1
// timeout2

Vue

生命周期

beforeCreate

created

beforeMount

mounted

beforeUpdate

updated

beforeDestroy

destroyed

React

React 的设计遵循单向数据流模型 ,也就是说,数据均是由父组件流向子组件。

Hooks

让组件在不使用 class 的情况下拥有 state,所以就有了生命周期的概念,所谓的生命周期其实就是 useStateuseEffect()useLayoutEffect()

useEffect componentDidMount, componentDidUpdate ,componentWillUnmount

	// componentDidMount/componentWillUnmount
useEffect(()=>{
  // 需要在 componentDidMount 执行的内容
  return function cleanup() {
    // 需要在 componentWillUnmount 执行的内容      
  }
}, [])

生命周期

挂载阶段

  • constructor
  • static getDerivedStateFromProps
  • render
  • componentDidMount

更新阶段

  • static getDerivedStateFromProps
  • shouldComponentUpdate
  • render
  • getSnapshotBeforeUpdate
  • componentDidUpdate

卸载阶段

  • componentWillUnmount

static getDerivedStateFromProps

static getDerivedStateFromProps: 该函数在挂载阶段和组件更新阶段都会执行,即每次获取新的props 或 state 之后都会被执行在挂载阶段用来代替componentWillMount;在组件更新阶段配合 componentDidUpdate,可以覆盖 componentWillReceiveProps 的所有用法。

getSnapshotBeforeUpdate

getSnapshotBeforeUpdate: 该函数会在 render 之后, DOM 更新前被调用,用于读取最新的 DOM 数据。

Webpack

node

CSS

canvas