var声明提升
js是一个解释性语言类型,预解析就是在执行代码之前对代码进行通读
var关键字是,在内存中声明一个变量名 js在代码执行之前 会经历两个环节 解释代码 和执行代码
声明式函数 内存中 先声明一个变量名是函数 这个名代表的是函数
乘法表
// for (var i = 1; i < 9; i++) {
// for (var j = 1; j <= i; j++) {
// document.write('*')
// }
// document.write('<br>')
// }
// console.log(myname)
// var myname = 'kerwin'
// console.log(myname)
//var结果有声明提升 undefined kerwin
作用域
就是一个变量可以生效的范围
变量不是所有地方都可以使用,而且这个变量的使用范围就是作用域
全局作用域
全局是最大的作用域,在全局中定义变量可以用在任何地方
页面打开时,浏览器会自动生成一个全局作用域windows
这个作用域会一直存在 直到页面关闭就销毁了
前端存储数据方式
主要存在四种:cookie,localStorage,sessionStorage,indexedDB。
1、cookies: 在HTML5标准前本地储存的主要⽅式,优点是兼容性好,请求头⾃带cookie⽅便,缺点是⼤⼩只有4k,⾃动请求头加⼊cookie浪费流量,每个domain限制20个cookie,使⽤起来麻烦需要⾃⾏封装。
2、localStorage:HTML5加⼊的以键值对(Key-Value)为标准的⽅式,优点是操作⽅便,永久性储存(除⾮⼿动删除),⼤⼩为5M,兼容IE8+
3、sessionStorage:与localStorage基本类似,区别是sessionStorage当⻚⾯关闭后会被清理,⽽且与cookie、localStorage不同,他不能在所有同源窗⼝中共享,是会话级别的储存⽅式。
4、IndexedDB:是被正式纳⼊HTML5标准的数据库储存⽅案,
闭包产生原因
根据词法作用域的规则,内部作用域可以访问外部作用域
GC(垃圾回收)机制,如果变量被引用那么GC在回收时并不会回收该变量
function foo() {
let test1 = '变量1'
const test2 = '变量2'
let test3 = '变量3'
var innerBar = {
getName: function () {
console.log(test1)
return test2
},
}
return innerBar
}
var bar = foo()
bar.getName()
右边 Scope 项就体现出了作用域链的情况:Local 就是当前的 getName 函数的作用域,Closure(foo) 是指 foo 函数的闭包,最下面的 Global 就是指全局作用域,从“Local–>Closure(foo)–>Global”就是一个完整的作用域链。
注意⚠️:只有我们在内部函数中使用的变量才会被加入闭包(Closure)中。
缺陷
如果引用闭包的函数是一个全局变量,那么闭包会一直存在直到页面关闭;但如果这个闭包以后不再使用的话,就会造成内存泄漏。(如果引用闭包的函数是个局部变量,等函数销毁后,在下次 JavaScript 引擎执行垃圾回收时,判断闭包这块内容如果已经不再被使用了,那么 JavaScript 引擎的垃圾回收器就会回收这块内存)
规避:如果该闭包会一直使用,那么它可以作为全局变量而存在;但如果使用频率不高,而且占用内存又比较大的话,那就尽量让它成为一个局部变量。
JavaScript的变量存储机制
可以把堆认为是一个很大的内存存储空间,你可以在里面存储任何类型数据。但是这个空间是私有的,操作系统不会管在里面存储了什么,也不会主动的去清理里面的内容,因此在C语言中需要程序员手动进行内存管理,以免出现内存泄漏,进而影响性能。
但是在一些高级语言 如JAVA会有 垃圾回收(GC) 的概念,用于协助程序管理内存空间,自动清理堆中不再使用的数据。
栈
栈是内存中一块用于存储局部变量和函数参数的线性结构,遵循着先进后出的原则。数据只能顺序的入栈,顺序的出栈。当然,栈只是内存中一片连续区域一种形式化的描述,数据入栈和出栈的操作仅仅是栈指针在内存地址上的上下移动而已。
但需要注意的是:内存中栈区的数据,在函数调用结束后,就会自动的出栈,不需要程序进行操作,操作系统会自动回收,也就是:栈中的变量在函数调用结束后,就会消失。 这也正是栈的特点:无需手动管理、轻量、函数调时创建,调用结束则消失
除了局部变量,其他的全都存在堆中。根据变量的数据类型,分为以下两种情况:
如果是基础类型,那栈中存的是数据本身。
如果是对象类型,那栈中存的是堆中对象的引用。
JavaScript的设计模式
- 工厂模式
- 构造器模式
- 原型模式
- 抽象工厂模式
原型模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>原型模式</title>
</head>
<body>
<script>
// function Employee(name,age){
// this.name = name;
// this.age = age;
// }
// Employee.prototype.say = function(){
// console.log(this.name,this.age);
// }
class Employee{
constructor(name,age){
this.name = name;
this.age = age;
}
}
</script>
</body>
</html>
构造器模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>构造器模式</title>
</head>
<body>
<script>
var employee1 = {
name:'keke',
}
var employee2 = {
name:'keke_2',
}
function Employee(name,age){
this.name = name;
this.say =function(){
console.log(this.name)
}
}
let employee = new Employee('keke')
</script>
</body>
</html>
工厂模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
function UserFactory(role) {
switch(role){
case "0":
return new User("superadmin");
break;
default:
throw new Error("参数错误")
}
}
</script>
</body>
</html>
抽象工厂模式
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<script>
class User {
constructor(name, role, pages) {
this.name = name;
this.role = role;
this.pages = pages;
}
welcome() {
console.log("Welcome");
}
dataShow() {
throw new Error("抽象未实现");
}
}
class SuperAdmin extends User {
constructor(name){
super(name, "Super Admin",["home"]);
}
dataShow(){console.log("superadmin");}
}
</script>
</body>
</html>