理论杂记
Posted 李耀书
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了理论杂记相关的知识,希望对你有一定的参考价值。
1、this
的指向
- 关于
this
的指向是一个比较关键的问题,不论什么时候我们都能遇到
首先:
-
在全局中
function foo() { var length = 10; console.log(this);//window } var length = 5; foo(); // 5
此时的
this
指向的是全局window
-
在构造函数中
function A(name, age) {
this.name = name;
this.age = age;
console.log(this); // A {name: "张三", age: 18}
}
var foo = new A('张三', 18);
此时的
this
指向的是new
出来的实例对象。
- 在函数被调用时
var b = {
AA: function a() {
console.log(this); //{AA: ƒ}
}
}
b.AA()
console.log(this); //window
谁调用
this
,那么this
就指向谁。
call、apply、bind
中的this
被强绑定在指定的那个对象上;
var name = '张三';
function fun() {
console.log(this.name);
}
var obj = {
name: '李四'
};
fun(); // 张三
fun.apply(obj); //李四
- 箭头函数中的
this
function Person() {
this.age = 0;
setInterval(() => {
console.log(this); //Person {age: 3}
// 回调里面的 `this` 变量就指向了期望的那个对象了
this.age++;
}, 3000);
}
var p = new Person();
箭头函数中的
this
指向的是父级的上下文。
2、事件模型:事件委托、代理?以及让如何让事件先冒泡后排序?
事件模型:
- 所谓的事件模型就是一种观察者模式的体现,就是当对应的事件被触发时,监听该事件的所有监听函数都会被调用。
- 观察者模式:又叫订阅者模式,他可以让多个观察者对象同时监听同一个主题对象。当这个主题对象的状态发生变化时同时所有的订阅者,使他们做出反映。
事件代理/委托:
- 事件在冒泡过程中会上传到父节点,因此可以把子节点的监听函数定义在父节点上,有父节点的监听函数统一处理。
<div id="box">
<input type="button" value="按钮" id="btn">
<input type="button" value="按钮2" id="btn2">
<input type="button" value="按钮3" id="btn3">
</div>
<script>
var box = document.getElementById('box');
box.addEventListener('click', function (event) {
console.log(1);
});
</script>
事件冒泡:
- 就是事件自上而下的过程,例如:
<div id="div1">我是div1
<div id="div2">我是div2
<div id="div3">我是div3
<div id="div4">我是div4</div>
</div>
</div>
</div>
var div1 = document.getElementById("div1");
var div2 = document.getElementById("div2");
var div3 = document.getElementById("div3");
var div4 = document.getElementById("div4");
div1.addEventListener("click", function () {
alert("我是div1");
})
div2.addEventListener("click", function () {
alert("我是div2");
})
div3.addEventListener("click", function () {
alert("我是div3");
})
div4.addEventListener("click", function () {
alert("我是div4");
})
- 在点击
div4
的时候,执行顺序是4-3-2-1.
如何让事件先冒泡后排序
var arr = [2, 3, 4, 5, 2, 34, 21, 12, 21]
for (var i = 0; i < arr.length - 1; i++) {
for (var j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
var str = arr[j] //当后一项大于前一项
arr[j] = arr[j + 1]
arr[j + 1] = str
}
}
}
console.log(arr);
3、对象和面向对象
什么是对象?
- 抽象【类】实例化的集合。
- 拥有属性和方法的一个集合
什么是面向对象?
- 可以看做是面向事件的结果,是相对于面向过程来说的,面向过程就是实现这一事件结果的具体过程。
- 面向对象是模型化的,其中包括三大特性:封装、继承、多态。
- 封装:对于一些公共方法的封装,通过调用来使用这个封装。
- 继承:从已有的对象下继承出新的对象。
- 多态:一个变量在引用不同类型的情况下的不同状态。多态开发在开发组件和模块化开发的时候能节省很多资源。
总结:
js
本身就是基于面向对象构造出来的(例如:JS
中有很多内置类,Array,Object,Function,String
;像Promise就是Es6
中新增的一个内置类,我们可以基于new Promise
来创建一个实例,管理异步编程;一般我们有的
Vue/REACT/JQUWEY
也都是基于面向对象构建出来的,他们都是类,平时开发是都是创建他们的实例来操作的我们自己真实的项目中,也封过一些组件插件指令(面向对象,插件:Node路由)他们也是基于面向对象开发的,这也可以创造不同的实例,来管理私有属性和公有的方法。
4、for…in和for…of的区别
- 遍历数组
var arr = [99,88,66,77];
for(let i in arr){
console.log(i); //0,1,2,3
}
for(let i of arr){
consoel.log(i); //99,88,66,77
}
for...in
遍历的是key
值。for...of
遍历的是vlaue
值
- 遍历字符串
同上
- 遍历对象
var a = {
id: 0,
name: '张三'
}
for (let key in a) {
console.log(key); //id,name
}
// for(let key of a){
// console.log(key);//: a is not iterable【可迭代对象】
// }
for (let key of Object.keys(a)) {
console.log(key); //id,name
}
for...in
遍历出来的是key值,for…of遍历出来的也是key
值,但是要配合Object.keys()
来使用,否则报错
5、查找数组重复项
function res(arr) {
var temp = [];
arr.forEach(function (item) {
if (arr.indexOf(item) !== arr.lastIndexOf(item) && temp.indexOf(item) === -1) {
temp.push(item)
}
})
return temp;
}
var arr = [1, 2, 4, 4, 3, 3, 1, 5, 3];
console.log(res(arr))
function res(arr) {
var temp = [];
arr.sort().sort(function (a, b) {
if (a === b && temp.indexOf(a) === -1) {
temp.push(a)
}
})
return temp;
}
var arr = [1, 2, 4, 4, 3, 3, 1, 5, 3];
console.log(res(arr))
6、数组扁平化
- 数组扁平化是指将一个多维数组变为一维数组.
1、toString
&split
var arr = [1, [2, 3, [4, 5]]]
function flatten(arr) {
return arr.toString().split(',').map(function (item) {
return Number(item);
})
}
flatten(arr)
console.log(flatten(arr)); //[1, 2, 3, 4, 5]
2、扩展运算符
var arr = [1, [2, 3, [4, 5]]]
function flatten(arr) {
while (arr.some(item => Array.isArray(item))) {
arr = [].concat(...arr);
}
return arr;
}
flatten(arr)
console.log(flatten(arr)); //[1, 2, 3, 4, 5]
3、递归
function flatten(arr) {
var res = [];
arr.map(item => {
if(Array.isArray(item)) {
res = res.concat(flatten(item));
} else {
res.push(item);
}
});
return res;
}
7、垃圾回收机制
1、什么是垃圾回收机制?
- 浏览器
javascript
具有自动回收机制。
执行环境会负责管理代码在执行过程中使用的内存。
- 原理
垃圾收集器会定期【周期性】的找出不在使用的变量,然后释放内存。
在执行过程中计算机【
gC
】会停止响应其他的操作。
- 注意:
只有函数内部的变量才会被回收。全局变量是不会被回收的。
2、垃圾回收的方式
- 标记清除
在
js
中最为常用的就是 标记清除,当变量进入环境是,也就是在函数中声明一个变量,就会将这个变量标记为进入环境
,在变量离开环境的时候,就会将这个变量标记为 离开环境,从逻辑上讲,是永远不能释放 进入环境的变量所占用的内存,因为只要执行流进入相应的环境,就会用到它们。
- 引用计数
引用计数的含义就是跟踪记录每个值被应用的次数
- 当声明一个变量并将一个引用类型赋给这个变量的时候,那么这个值得引用次数就是1,如果同一个值又被赋给了另一个变量,那么这个值得的引用次数加1,
- 但是当这个包含对这个值的引用变量有取得了另外一个值,那么这个值得引用次数减1,当这个值得引用次数变成0的时候,则说明无法访问这个值了,因而就会将其所占用的内存空间给收了回来。
- 这样的话,当垃圾回收器下次运行的时候,他就会释放那些引用次数为0的值所占用的内存。
缺点:容易造成内存泄漏。
【在函数执行时,两个对象的属性都被引用,这两个对象的引用次数为2,在函数执行完,两个对象都离开了作用域,但是内存还会存在。】
8、iframe
的优缺点有哪些?
使用场景
- 加载别的网站内容,例如广告
- 在上传图片时,不用flash实现不刷新
- 跨域访问的时候可以用到
iframe
,使用iframe
请求不同域名下的资源 - 典型系统结构,左侧是功能树,右侧是常见的table或者表单一类。为了每一个功能,单独分离出来,采用
iframe
ajax
上传文件
优点:
- 重载页面时不需要重载整个页面,只需要重新加载页面中的一个框架页(减少数据的传输,减少网页的加载时间)
- 技术简单,使用方便,主要应用于不需要搜索引擎来搜索的页面。
- 方便开发,减少代码的重复率,
缺点:
- 会产生很多的页面,不易于管理。
- 不易于打印;在控制台查看。
- 多框架的页面会增加服务器的
http
请求。 - 路蓝旗的后退按钮无效。
- 由于去点太多,
html5
已经不在支持
9、函数柯力化
- 当一个函数有多个参数的时候,先传递一部分参数(这部分参数以后永不改变)调用它;然后返回一个新的函数接受剩余的参数,返回结果。
- 创建一个函数,该函数接受一个或者多个
function
的参数,如果function
中所需要的参数都被提供则执行function
并返回执行结果,否则,继续返回该函数并等待剩余的参数。- 参数就是需要柯力化的函数,
- 返回值就是柯力化后的函数
- 目的就是将一个多元函数转换成一个一元函数。
- 在函数柯力化的时候,在柯力化内部使用闭包,对函数的参数进行缓存,柯力化让函数变得更加的灵活。
10、window
的onload
事件和domecontentloaded
主要区别:
-
调用时机不同
-
DocumentContentLoaded
在DOM
树加载完之后立刻触发, -
DOM
树加载完成之后,继续加载图片等外部文件,加载完成之后,onload
事件触发。
以上是关于理论杂记的主要内容,如果未能解决你的问题,请参考以下文章
因果推断杂记——因果推断与线性回归SHAP值理论的关系(十九)