推荐使用网页查看,可以点击问题跳转到解析,持续更新中,祝大家都能找到合适的工作~
【个人学习笔记,包含各种前端,及工作中遇到的问题,欢迎大家关注我
会持续更新基本每天都更新】
(╹▽╹) 笔记地址地址:十二的前端笔记-语雀
原型链:js对象独有的__proto__属性,当访问一个对象的属性时,如果该对象内不存在这个属性,会去它的__proto__属性所指向的那个对象(父对象)里找,直到null
proto:对象都有私有属性__proto__(),从对象指向实例原型
prototype:函数独有的属性,从一个函数指向一个对象,包含所有实例可共享的属性和方法,任何函数创建时,会默认创建该函数的prototype对象
constructor:实例的构造函数(constructor)属性,指向实例
所有函数和对象最终都是由Function构造函数得来,所以constructor属性的终点就是Function这个函数。
基本数据类型:名字和值都存在栈中
引用数据类型:名字在栈中,值在堆中,栈内存会提供一个引用地址,指向堆内存中的值
浅拷贝:1.for只遍历第一层 2.assign 3. =直接赋值
深拷贝:1.递归遍历所有层级 2.利用JSON对象【JSON.stringfy() JSON.parse()】 3.通过jQuery的extend方法实现深拷贝 4.lodash函数库实现深拷贝 5.用slice实现对数组的深拷贝,slice() 方法可从已有的数组中返回选定的元素。6.使用扩展运算符实现深拷贝 8.Reflect法 9.用concat实现对数组的深拷贝 10.直接使用var newObj = Object.create(oldObj),可以达到深拷贝的效果。11.手动实现深拷贝 7.如对象的value是基本类型,可以用Object.assign来实现深拷贝,但是要把它赋值给一个空对象
assign第一层是深拷贝,第二层以后是浅拷贝
function deepClone2(obj) {
var _obj = JSON.stringify(obj),
objClone = JSON.parse(_obj);
return objClone;
} // 无法实现对对象中方法的深拷贝,会显示为undefined
var array = [1,2,3,4];
var newArray = $.extend(true,[],array); // true为深拷贝,false为浅拷贝
let result = _.cloneDeep(test)
栈和堆
闭包:https://www.yuque.com/nizhidaoba/ufw9so/no2gre
闭包函数:声明在一个函数中的函数,叫做闭包函数。
闭包:内部函数总是可以访问其所在的外部函数中声明的参数和变量,即使在其外部函数被返回(寿命终结)了之后。
参数和变量不会被垃圾回收机制回收
function a() {
var name = 'Shier'
return function(){
return name
}
}
var b = a()
console.log(b())
// 通过返回函数中返回的内部变量,使函数外部能够使用和访问函数内部变量
setTimeout有两个参数,第一个参数为一个函数,我们通过该函数定义将要执行的操作。第二个参数为一个时间毫秒数,表示延迟执行的时间。
var timer = setTimeout(function() {
console.log('如果不清除我,我将会一秒之后出现。');
}, 1000)
clearTimeout(timer); // 清除之后,通过setTimeout定义的操作并不会执行
for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log(i);
}, i*1000 );
}
// 上述结果返回总为6
for (var i=1; i<=5; i++) {
(function(i) {
setTimeout( (function timer() {
// 或者在这里使用闭包
console.log(i);
})(i), i*1000 );
})(i)
}
// 使用闭包将值存住,输出为123456
console的返回值中,会有两行,一行是一个唯一的id,其他的是输出的内容
每个setTimeout在执行时,会返回一个唯一ID。在使用时,常常会使用一个变量将这个唯一ID保存起来,用以传入clearTimeout,清除定时器。
DOM事件流:事件捕获,目标阶段,事件冒泡
addEventListener(‘click’,function(event){触发事件}, false)默认在事件冒泡阶段触发,默认值false
事件委托:event.currentTarget:事件绑定的元素(绑定在父级元素)
event.target:触发事件的源头(所点击的子元素)target:事件目标
事件委托利用了事件冒泡和event.target,当有一系列子元素都需要绑定事件时,只需要将事件绑定在父元素即可
a.一般函数,this指向全局对象window;
b.在严格模式下"use strict",为undefined.
c.对象的方法里调用,this指向调用该方法的对象. 【this指的是,调用函数的那个对象】
d.构造函数里的this,指向创建出来的实例.
call,apply,bind,改变函数运行时的指向,当第一个参数为null或undefind时,指向window
call:传入参数列表,改变函数指向并立即调用,第一个参数同apply,第二个参数必须是单个参数列表,不能是数组
apply:可以传入数组,第一个参数:要绑定给this的值 第二个参数:参数列表(可以是数组)
bind:改变this指向后,返回的是函数
var obj = {
name: 'Dot'
}
function printName() {
console.log(this.name)
}
var dot = printName.bind(obj)
console.log(dot) // function () { … }
dot() // Dot
//bind 方法不会立即执行,而是返回一个改变了上下文 this 后的函数。
//而原函数 printName 中的 this 并没有被改变,依旧指向全局对象 window。
var a = 1
var obj1 = {
a:2,
fn:function(){
console.log(this.a)
}
}
obj1.fn()//2
//此时的this是指obj1这个对象,obj1.fn()
//实际上是obj1.fn.call(obj1),事实上谁调用这个函数,this就是谁
点击页面,依次输出:document和window对象
解析:点击页面监听click事件属于方法调用,this指向事件源DOM对象,即obj.fn.apply(obj),setTimeout内的函数属于回调函数,可以这么理解f1.call(null,f2),所以this指向window。
document.addEventListener('click', function(e){
console.log(this);
setTimeout(function(){
console.log(this);
}, 200);
}, false);
concat() 连接两个或更多的数组,并返回结果。
join() 把数组的所有元素放入一个字符串。元素通过指定的分隔符进行分隔。
pop() 删除并返回数组的最后一个元素
push() 向数组的末尾添加一个或更多元素,并返回新的长度。
reverse() 颠倒数组中元素的顺序。
shift() 删除并返回数组的第一个元素
slice() 从某个已有的数组返回选定的元素
sort() 对数组的元素进行排序
splice() 删除元素,并向数组添加新元素。
toSource() 返回该对象的源代码。
toString() 把数组转换为字符串,并返回结果。
toLocaleString() 把数组转换为本地数组,并返回结果。
unshift() 向数组的开头添加一个或更多元素,并返回新的长度。
valueOf() 返回数组对象的原始值。
set:不重复的值得集合【let set = new Set([1, 2, 2, 3]) // [1, 2, 3]
add(value):添加某个值,返回 Set 结构本身。
delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
has(value):返回一个布尔值,表示该值是否为Set的成员。
clear():清除所有成员,没有返回值。—
keys():返回键名的遍历器
values():返回键值的遍历器
entries():返回键值对的遍历器
forEach():使用回调函数遍历每个成员
weakSet:成员只能是对象
map
instanceOf,Object.prototype.toString.call()的区别
不等于,因为浮点数计算是不精确的
【基本类型 5】string、number(浮点数,整数,NAN)、boolean、null、undefined
【引用类型 1】object(data,function,array)
【es6 1】symbol
【bigInt】Javascript 中的任意精度整数,可以安全存储和操作大整数。即始超出 Number 能够表示的安全整数范围。是 chrome 67中的新功能。
for:for(let i=0; i<10; i++)i:下标 arr[i]:值
for…each: arr.forEach((item,index) => {}) 遍历数组,不能使用break,contintue,return
for…in:for (var i in arr){ // i是下标(索引)} i:下标 arr[i]:值 原型链上的所有属性都将被访问 arr.hasOwnProperty(i)可以判断是否在实例上,在实例上才会被返回
for…of: 只能遍历数组
map: 有返回值,可以返回结果数组,不能遍历对象,只能遍历数组或对象数组
var arr = [‘星期一’, ‘星期二’, ‘星期三’];
var a = arr.map(function(item){
console.log(item)
return item === ‘星期二’
})
console.log(a)
1.new Set(arr)
2.for嵌套,两层循环,如果第二个等于第一个,删掉第二个,用splice方法
splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目。
注释:该方法会改变原始数组。
3.indexOf:建一个空数组,循环目标数组,判断新数组中是否有当前单参数,没有就push,有就跳过
4. includes:查找数组中是否有某个元素
高度塌陷:
父元素在文档流中高度默认是被子元素撑开的,当子元素脱离文档流以后,将无法撑起父元素的高度,也就会导致父元素的高度塌陷。父元素的高度一旦塌陷, 所有标准流中元素的位置将会上移,导致整个页面的布局混乱
解决方法:
(1)浮动元素后添加
(2)使用after伪类,向父元素后添加一个块元素,并对其清除浮动。该种方式的原理和方法一原理一样,但是不用向页面中添加多余的结构。
#div::after {
content: “”;
display: block;
clear: both
}
(3)开启父元素的BFC,为父元素添加样式
overflow:hidden;
(4)手动为父元素添加高度。
position四种定位方式:
static:默认值,不接受top等参数
fixed:依据窗口定位(fixed定位在IE7和IE8下需要描述!DOCTYPE才能支持。)
relative:相对于自身的位置
absolute:相对于最近的定位的父元素,如果都没有,相对于html
sticky:固定一部分内容,类似于吸顶的效果
z-index的作用:z轴上的层级问题
创建:
createDocumentFragment() //创建一个DOM片段
createElement() //创建一个具体的元素
createTextNode() //创建一个文本节点
添加:appendChild()
移出:removeChild()
替换:replaceChild()
插入:insertBefore()
复制:cloneNode(true)
查找:
getElementsByTagName() //通过标签名称
getElementsByClassName() //通过标签名称
getElementsByName() //通过元素的Name属性的值
getElementById() //通过元素Id,唯一性
1)opacity:0;不显示,占据空间
2)visibility: hidden; 属性会继承,如果子元素想可见,需要visibility:visible
3)display: none; 盒模型不生成
4)z-index:-999
eval() 函数可计算某个字符串,并执行其中的的 JavaScript 代码。
a=[1,3,5,9]
r=eval(a.join(’+’))
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
return total + num;
}
function myFunction(item) {
document.getElementById(“demo”).innerHTML = numbers.reduce(getSum);
}
方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
arr.reduce(callback,[initialValue])
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
//简单用法:求和求积
var arr = [1, 2, 3, 4];
var sum = arr.reduce((x,y)=>x+y)
var mul = arr.reduce((x,y)=>x*y)
console.log( sum ); //求和,10
console.log( mul ); //求乘积,24
//高级用法
//(1)计算数组中每个元素出现的次数
//(2)数组去重
//(3)将二维数组转化为一维
//(4)将多维数组转化为一维
//(5)、对象里的属性求和
普通函数:无返回值,person()调用,
构造函数:返回实例对象,let per = new Person()调用,内部用this来构造属性和方法
构造函数流程:
1.立刻在堆内存中创建一个对象
2.将新建的对象设置为函数中的this
3.逐个执行函数中的代码
4.将新建对象作为返回值
function Person(name,job,age)
{
this.name=name;
this.job=job;
this.age=age;
this.sayHi=function()
{
alert(“Hi”)
}
}
1)let和const不存在变量提升
2)let:块级作用域
3)const:声明的变量不允许改变,声明的时候必须赋值
4)对于复合类型的变量(如数组,对象),const保存的只是地址,里面的内容是可以改变的,想要整个对象都不允许改变,可以使用Object.freeze()方法
5)一切用var声明的全局变量都是window的属性
6)有声明和没有声明的全局变量都会成为window的属性,有什么区别呢?
没有声明的变量可以被删除,而声明的不可以
7)用let ,const 和 calss声明的全局变量不归window所有
数组解构:可以设置默认值,可以赋值给新数组(修改新数组不会改变老数组)
let a = [0,1,2,3]
let b = [...a]
b.push(4)
console.log(a) // [0,1,2,3]
console.log(b) // [0,1,2,3,4]
对象解构:对象的解构赋值是根据key值进行匹配
let {
name="swr",age} = {
age:28} // 默认值
给函数传不确定参数数量时,是通过arguments来获取的
function sum(...args){
// 使用...扩展运算符,arg要放在最后一个参数
//使用原始的arguments。是个伪数组,不利于操作,...args是数组方便操作
console.log(args) // [ 1, 2, 3, 4, 5, 6 ] args是一个数组
return eval(args.join('+'))
}
console.log(sum(1,2,3,4,5,6)) // 21
// 但是可以用Array.from把伪数组转为数组
let likeArr = {
"0":1,"1":2,"length":2 }
let arr = Array.from(likeArr)
console.log(arr) // [1,2]
不适合使用箭头函数的场景
const obj = {
x: 1,
print: () => {
console.log(this === window); // => true
console.log(this.x); // undefined
}
};
obj.print();
//解析:print 方法用了箭头函数,其内部的 this 指向的还是上下文 window
//上下文中并没有定义 x,所以 this.x 输出为 undefined。
//解决办法:用 ES6 的短语法,或者传统的函数表达式print(){}都可以。
function Cat (name) {
this.name = name;
}
Cat.prototype.sayCatName = () => {
console.log(this === window); // => true
return this.name;
};
const cat = new Cat('Miao');
cat.sayCatName(); // => undefined
// 使用箭头函数会导致运行时的执行上下文错误
Cat.prototype.sayCatName = function () {
console.log(this === cat); // => true
return this.name;
};
// sayCatName 变回传统的函数表达式之后,被调用时的执行上下文就会指向新创建的 cat 实例。
https://zhuanlan.zhihu.com/p/62729974
2.写 React/Vue 项目时为什么要在组件中写 key,其作用是什么?
key 的作用是为了在 diff 算法执行时更快的找到对应的节点,提高 diff 速度。vue 和 react 都是采用 diff 算法来对比新旧虚拟节点,从而更新节点。在 vue 的 diff 函数中。可以先了解一下 diff 算法。
在交叉对比的时候,当新节点跟旧节点头尾交叉对比没有结果的时候,会根据新节点的 key 去对比旧节点数组中的 key,从而找到相应旧节点(这里对应的是一个 key => index 的 map 映射)。如果没找到就认为是一个新增节点。而如果没有 key,那么就会采用一种遍历查找的方式去找到对应的旧节点。一种一个 map 映射,另一种是遍历查找。相比而言。map 映射的速度更快。
$route: 正在跳转的路由对象,可以从里面获取name,path,params,query等
r o u t e r : 是 v u e R o u t e r 的 实 例 , 相 当 于 一 个 全 局 的 路 由 对 象 , 包 含 很 多 属 性 和 子 对 象 , 例 如 h i s t o r y 对 象 , t h i s . router:是vueRouter的实例,相当于一个全局的路由对象,包含很多属性和子对象,例如history对象,this. router:是vueRouter的实例,相当于一个全局的路由对象,包含很多属性和子对象,例如history对象,this.router.push()
性能更高,因为他就是一个函数
由于是无状态组件,所以,无论props会否变更,都会重新刷新这个组件
https://segmentfault.com/a/1190000016774551
const head = (props) => {
return
https://www.jianshu.com/p/825b7b4c401d
https://segmentfault.com/a/1190000019834626
https://www.jianshu.com/p/0aae7d4d9bc1
在this.setState({})之后打印信息,会出现延迟,想要同步需要在this.setState({},()=>{回调函数}),在回调函数中打印数据,可以同步
https://www.jianshu.com/p/c41bbbc20e65
https://www.jianshu.com/p/b666ac2407b0
http://www.ruanyifeng.com/blog/2016/09/redux_tutorial_part_one_basic_usages.html
npm常用操作
https://www.nowcoder.com/ta/front-end
https://www.cnblogs.com/soyxiaobi/p/9963019.html
如果没有传入 path 片段,则 path.resolve() 会返回当前工作目录的绝对路径。
console.log(__filename);
// 打印: /Users/mjr/example.js
console.log(__dirname);
// 打印: /Users/mjr
1)source-map:false:不生成.map文件
2)路由中配置reslove 按需加载
3)大的三方包:echert等,用《script标签引入,webpack中去掉这些打包
worker:https://juejin.im/post/6844903821278199822?utm_medium=hao.caibaojian.com&utm_source=hao.caibaojian.com
tomcat的压缩机制:https://blog.csdn.net/baidu_16250655/article/details/88688299
nvm:nodejs 版本管理工具。一个 nvm 可以管理很多 node 版本和 npm 版本。
nodejs:在项目开发时的所需要的代码库
npm:nodejs 包管理工具。
在安装的 nodejs 的时候,npm 也会跟着一起安装,它是包管理工具。
npm 管理 nodejs 中的第三方插件
关系:
nvm 管理 nodejs 和 npm 的版本
npm 可以管理 nodejs 的第三方插件