杂记(2019/12/16-22)
请女孩子大声朗读:
我可以温柔文静、善解人意,也可以狭隘自私、不近人情。我活着是为了找寻属于我自己的快乐,而不是为了追逐谁为谁停留等待。我不在乎是否有人爱我,因为我是一朵永生花,爱不爱,我都永远美丽芬芳可爱。
从昨天开始,实验室进行两周一次的电话考核。(被问得自闭了呜呜呜)
找到的需要巩固的知识点:
- 内存泄漏
- 执行上下文
- (√)匿名函数
- (√)sort并不会立刻排序,而是转换二进制
- bigInt
- (√)立即执行函数
- this五种绑定
2019/12/16-17 Two days
周一课设结束,立刻就去做物理光学的测试考了。导致周一的学习进度为0%。
开了一本新的手账本,准备尝试一下新的风格 -> 余白,看了别人的手账,觉得别人的余白就很高级。
让自己安静了一天,决定做一个断舍离。
JS中sort函数的底层实现机制
sort()
方法用于对数组进行排序,并返回排序好的数组,不会改变原来的数组。该注意的是:sort()
方法是根据字符串的Unicode码点进行默认排序!!!
之前的错误认知: 根据数值大小进行默认排序。于是下面的栗子直接打脸…
[11,1,22,2,3].sort(); // 结果:[1, 11, 2, 22, 3]
所以,为了可以按照字符编码顺序来进行排序,那么就需要先把数组里的元素转换成字符串。
如果想按照其他方式进行排序,那么我们只需要提供比较函数就可以了。
// 升序
[11,1,22,2,3].sort((a,b) => a-b); // 结果:[1, 2, 3, 11, 22]
// 降序
[11,1,22,2,3].sort((a,b) => b-a); // 结果:[22, 11, 3, 2, 1]
叨叨,这里a - b
不要理解成a减b的意思,可以理解成26字母中a到b,因为26字母中b比a大,所以就是升序;相反,b - a
就是降序。
匿名函数
匿名函数:
function() { console.log("我是匿名函数"); } // 但是如果这样写,在运行的时候会报错 // 外面包裹一个()就可以了
要叨叨一点的是,箭头函数并不是简单的匿名函数的语法糖,它们两者之间最大的区别就是:箭头函数内部的this是词法作用域,而匿名函数的this指向运作时调用该方法的对象。
怎么使用匿名函数?
很简单,在匿名函数后加一个()就行了,如果需要传值,那就写括号里
(function(msg) {
console.log(msg);
})('我是匿名函数')
应用匿名函数
实现闭包:
function fn() { let a = 1; return function() { console.log(a) } } let bar = fn();
模拟块级作用域(私有作用域),减少全局变量。执行完匿名函数,块级作用域中的变量就会被销毁,从而节省内存空间。
> 其实JS中是没有块级作用域的,但是ES6增加了块级作用域,块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
(function(){
//这里是我们的块级作用域(私有作用域)
})();
立即执行函数(IIFE)
由于ES5没有块作用域,所以立即执行函数就获得了广泛应用。(不过ES6加了块作用域,导致立即执行函数没有那么必要了)
立即执行函数的两种表达形式:
// 第一种
(function(i) {
...
})()
// 第二种
(function(i){
...
} ())
该注意的是,立即执行函数后面都带着一个(),而且函数体其实是函数表达式,通过(),-,+,!运算符将函数声明转换成函数表达式,达到立即执行的效果。
(function(i) {
console.log(i) // ()运算符,输出123
})(123);
!function(i) {
console.log(i) //!运算符,输出123
}(123);
+function(i) {
console.log(i) // +运算符,输出123
}(123);
-function(i) {
console.log(i) // -运算符,输出123
}(123);
使用立即执行函数的好处,就是上面说的开辟一个块作用域,避免破坏污染全局的命名空间。
this的五种绑定(未完)
this
的绑定规则有以下五种:
默认绑定(严格/非严格模式)
显示绑定(call、apply方法)
隐式绑定
new
绑定箭头函数绑定
……
(明天搞明天搞,我现在去复习一下模电呜呜呜,雨露均沾!)
2019/12/18 Wednesday
this的五种绑定(完)
首先需要明确的一点是,this并不是在函数被定义时绑定,而是在函数被调用时。
this
的绑定规则有以下五种:
- 默认绑定(严格/非严格模式)
- 显示绑定(call、apply方法)
- 隐式绑定
new
绑定- 箭头函数绑定
其实一般都说四种吧,但是我觉得把箭头函数的this放在一起整理比较好。(潜意思:我就要我就要我就要,但是如果你和我说这样不行,我还是会听听的!)
1. 默认绑定
独立函数调用:直接调用函数,使用默认绑定;
严格模式:this绑定到
undifined
;非严格模式:函数在非严格模式时将默认绑定到全局对象上。
function foo() { console.log(this.a); } let a = 1; foo() // 1
2.隐式绑定
函数在被调用时,如果存在上下文对象,那么this会绑定到这个上下文对象上。
function foo() {
console.log(this.a)
}
let obj = {
a: 1,
foo: foo
};
let a = 2;
obj.foo(); // 1
显然这个函数foo()
被调用时落脚点是obj对象。
let foo = function () {
console.log(this.a)
}
let obj2 = {
a: 2
foo: foo
}
let obj1 = {
a: 1
obj2: obj2
};
obj1.obj2.foo(); // 2
(这个我没想好要怎么讲…先留着…)
但是应用隐式绑定this存在一个问题,那就是隐式丢失。
看下面这个栗子:
function foo() {
console.log(this.a)
}
let obj = {
a: 1,
foo: foo
};
let a = 2;
let bar = obj.foo;
bar(); // 2
bar是指向obj.foo的一个引用,可是实际上,它引用的是foo函数本身,所以在调用bar()
时,已经是作为独立函数调用了,这个时候执行的是默认绑定。
3. 显示绑定
通过call()、apply()的方法绑定。接受一个参数,为绑定的对象,在函数调用时,将this绑定到这个对象上。
function foo() {
console.log(this.a);
}
let obj = {
a: 1,
};
let a = 2;
foo.call(obj) // 1
在看刚才那个隐式丢失的栗子:
function foo() {
console.log(this.a)
}
let obj = {
a: 1,
foo: foo
};
let a = 2;
let bar = obj.foo;
bar.call(obj); // 1
所以用call()、apply()可以解决隐式丢失的问题。
4. new绑定
构造函数其实是使用new
操作调用的一个普通函数,包括内置函数在内的所有函数都可以用new
操作符来调用,称为构造函数调用。
实际上并不存在所谓的构造函数,确切的说是函数的构造调用。
new
一个函数会执行下面操作:
- 创建一个新的对象;
- 将这个新对象的__proto__指向构造函数的原型(prototype);
- 使用这个新对象调用函数,将函数的this绑定到这个新对象上;
- 如果函数里没有返回对象,那么返回这个创建的新对象。但是如果return 了一个对象,那么这个新对象作废。
function Foo(a) {
this.a = a;
}
let bar = new Foo(2);
console.log(bar.a); // 2
5. 箭头函数绑定
箭头函数和普通函数的this区别:
- 普通函数: this指向调用这个方法的对象(谁调用我,我的this就绑定谁);
- 箭头函数: this指向调用环境(在哪个环境下调用我,我的this就绑定谁)。
2019/12/21 Saturday
即使深陷泥潭,也要仰望星空
2019/12/22 Sunday
感觉杂记可能要停了,最近全部心思都在模电上了。
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达,可以邮件至 610193653@qq.com,谢谢啦!
文章标题:杂记(2019/12/16-22)
本文作者:zzzwyyy
发布时间:2019-12-17, 21:33:50
最后更新:2019-12-23, 23:27:48
原始链接:http://yoursite.com/2019/12/17/杂记(2019-12-16-22)/版权声明: "署名-非商用-相同方式共享 4.0" 转载请保留原文链接及作者。