js基础

变量提升

1
2
3
4
5
6
7
8
9
alert(a);
a();
var a = 3;
function a(){
alert(10)
}
alert(a)
a = 6
a()

解答

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 变量提升,函数在变量前面
function a(){
alert(10)
}
var a
// 函数和变量同名,如果变量没有被赋值则函数生效,否则变量生效
alert(a);
// 执行函数
a();
// 给a赋值,a为值3
a = 3;
function a(){
alert(10)
}
// 弹出a的值3
alert(a)
// 给a赋值为6
a = 6
// 报错,a不是函数,a值为6
a()

函数表达式

1
2
3
4
5
6
7
8
9
10
var a = function aaa(num){
aaa = num;
console.log(typeof aaa);
console.log(aaa);
return 1;
}
// 执行a(1),进入函数内部,内部打印为aaa类型function,因为aaa为只读,内容为函数体
a(1)
// undefined,aaa函数仅供a内部调用
console.log(typeof aaa);

this

1
2
3
4
5
6
7
8
9
10
11
12
13
14
// 谁调用this,this就指向谁,没人调用指window,箭头函数的this绑定父元素
this.test = 11;
var s = {
a:function(){
var test = 2
console.log(1+this.test)
console.log(this.test)
},
qq:2
}
var f = s.a.bind(this);
// new之后,this指定当前函数实例
new f();
// NAN undefined

简写的函数声明

1
2
3
4
5
6
7
8
9
10
11
// 简写的函数声明b(){}不能被实例化new
this.test = 11;
var s = {
a(){
console.log(1+this.test)
},
qq:2
}
var f = s.a.bind(this);
new f()
// 报错提示f is not a constructor

TDZ暂时性死区

代码块内,使用let、const命令声明变量之前,该变量都是不可用的

1
2
3
4
5
6
7
var a = 11
function fn(){
console.log(a)
let a = 3
}
fn()
// ReferenceError: Cannot access 'a' before initialization

原型链

1
2
3
4
function fn(){}
fn.prototype.a = 11
console.log(fn.a)
// undefined

new之后才会去原型链上找,函数有原型链,变量没有原型链

1
2
3
4
5
function fn(){}
fn.prototype.a = 11
var s = new fn()
console.log(s.a)
// 11

new之后如果有该属性则直接取值,否则去原型链上找
在原型链中,我们想要查找某一个对象的属性,如果该属性在当前对象所在的函数中查找,如果没有的话就会沿着原型链向上查找,找到的话就返回属性值,如果都没有的话就会返回undefined

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
this.a = 20;
var test = {
a:40,
init:()=>{
console.log(this.a)
function go(){
this.a = 60;
console.log(this.a)
}
go.prototype.a = 50;
return go;
}
};
var p = test.init();
p();
new(test.init())();


// 输出结果
// 20
// 60
// 60
// 60

// 如果是test.init(),其中this指向test;
// 但是var p = test.init(),是把test.init()赋值给p,是一个变量,此时this指向window
// 1. 第一次执行init,this指向window,a=20
// 2. 第二次为执行go,此时go将window的a改为60,打印60
// 3. 第三次为执行init,this指向window,a=60
// 4. 第四次为执行return出的go,a=60

总结

  1. 立即执行函数
  2. 闭包 内部函数可以访问外部函数的变量,把函数返回出去,闭包可以保护内部的变量,闭包造成内存泄漏,==null解决泄漏
  3. 原型链
    • 构造函数里的属性的优先级比原型链高
    • 面向对象编程的时候,js没有类的概念,可以用函数替代
    • constructor实际就是对应的那个函数
    • prototype按引用传递的,object.create原型链的副本
  4. 数值,字符串,布尔类型按值传递,对象,数组按引用传递
  5. 改变this的方法 call apply bind
  6. 函数提升 变量途胜 函数提升的级别高于变量提升
  7. jq内部有很多经典的写法,模块化编程的概念,闭包