js 基础总结(一)

一、Javascript

  • ECMAScript(ES):规定了js的一些基础核心的知识(变量、数据类型、语法规范、操作语句等)。
  • DOM: doucument object model 文档对象模型,里面提供了一些属性和方法,可以让我们操作页面中的元素。
  • BOM: browser object model 浏览器对象模型,里面提供了一些属性和方法,可以让我们操作浏览器。

    二、变量和常量

  • 变量:值是可以改变的。

  • 常量:值是不可以改变的。
// -> js中定义变量的形式      var  变量名: 值
//重点: 变量其实只是一个无意义的名字,他所代表意义都是其存储的那个值

num = 13 
// -> 让原有的num存储的变量改为13 (变量只能代表一个值)
// -> 任何一个具体的数据都是常量 例如:12就是一个常量
// -> 和变量类似,我们设置一个常量(也是一个名字),给其存储一个值,但是这个存储的值不能修改

const num= 12   
// ->  定义一个常量num ,给他存储了12,
// ->  num =13   报错  Uncaught TypeError ; Assi gnmentto constant variable. 存储的值是不能修改的

三、js中的数据类型

  • 基本数据类型
    1、number (数字)
    2、string (字符串)
    3、booler (布尔)
    4、null (空对象指针)
    5、undefined(未定义)

  • 引用数据类型
    1、object (对象数据类型有:{ }普通对象 、[ ]数组、 $/ 正则…)
    2、function (函数数据类型有:function() 普通函数、类等)

//重点: 基本类型是值类型  直接操作值的  引用类型操作的是地址所以叫数据引用类型

// -> 变量名没有什么实际意义,变量名所代表的是他所存储的值
    var a=12; 
    var b=a;
    b=13 
    console.log(a) => //12 

// -> 引用类型操作的是地址所以叫数据引用类型
    var n={name:"李四"};
    var m = n ;
    m.name = "张三";
    console.log(n.name)  => // 张三

// -> 对象是先开空间
    var m = {name:"小李"};
    var n = m  // n指向m的空间地址
    n={name:"小何"}  // n又开辟一个新的内存空间地址改变地址指向
    console.log(m.name)  =>// 小李

    function fn(){
        console.log('1')
    }

    console.log(fn)   // 输出函数本身
    console.log(fn()) // 把当前函数执行的返回结果(return 什么返回就是什么,不写默认undefined// 重点:
1.当浏览器加载html页面的时候,首先会提供一个供全局js代码执行环境---全局作用域window  
2.引用数据类型是按照空间地址(引用地址)来操作的 var n = {name:"李四"};
 * 先创建一个变量 n
 * 浏览器首先会开辟一个新的存储空间(内存空间),目的是把对象中需要存储的内容(键值对)分别的存储在这个空间中
 * 为了方便后期找到这个空间,浏览器给空间设定一个地址(16进制的)
 * 把空间的地址赋值给了变量

四、js中的堆栈内存

  • 栈内存:俗称叫做作用域(全局作用域 / 私有作用域)

    1.为js代码提供执行环境(执行js代码的地方)
    2.基本数据类型值是直接放在栈内存中的

  • 堆内存:存储引用数据类型值的(相等于一个存储的仓库)

    1.对象存储的是键值对
    2.函数存储的是代码字符串

// 重点:在项目中 我们的内存越少性能越好,我们需要把一些没用的内存处理掉
a、堆内存:
    1. var o={}  当前对象对应的堆内存被变量o占用,无法销毁
    2. o=null  null空对象指针(不知想任何的),此时上一次的堆内存就没有被占用了
    3. 谷歌浏览器会在空闲时间把没有被占用的堆内存自动释放(销毁/回收)
b、栈内存
    1.一般情况下,函数执行形成的内存,函数执行完,浏览器会把形成的栈内存自动释放,有时候执行完成,栈内存不能被释放。
    2.但是还有其他情况:函数执行完成,当前私有作用域(栈内存)中的某一部分内容被意外其他的东西(变量或者元素事件)占用了,
      当前的栈内存就不能被释放掉,也就形成了不销毁的私有作用域(里边的私有变量也不会销毁)
    3.全局作用域在加载页面的时候执行,关掉页面的时候销毁。

五、函数作用域以及闭包作用链

  • 变量提升(es6的let和const不存在变量提升)

    1、在当前作用域中,js代码自上而下执行之前,浏览器首先会把所有的var / function 关键字的进行提前的声明或者定义
    2、声明:var num; 在当前作用域告知我有 num这个名了
    3、定义:num =12 把声明的名字赋一个值
    4、带var关键字的只是提前声明一下,带funciton关键字的在变量提升阶段把声明和定义都完成了(变量提升到核心)
    5、在私有作用域声明的变量都是私有变量;闭包机制:私有作用域保护里面的私有变量不受外界的干扰
    6、在全局作用域当中,我们声明一个变量, 相当于给全局对象window增加了一个属性名 var a; <=> window.a = undefined

console.log(num)
console.log(fn)
var num  =13;
function fn(){
    console.log(a)
    var a =10 ;
    console.log(a)
}
fn()

1.1、定义变量带 var 和 不带 var 的区别

var: 在当前作用域当中声明一个变量,如果当前是全局作用域,相当于给全局对象window增加了一个属性名 
       var a <=> window.a
不带var:在全局作用域中仅仅是给全局对象设置了一个新的属性名 window.a

1.2、闭包和作用域链

1、闭包:函数执行形成私有作用域,保护里面私有变量不受外界干扰的这种机制叫闭包
2、但是在市面上,大多数开发者认为:函数执行,形成一个不销毁的作用域,除了保护私有变量意外还可以存储一些内容,这样的模式才是闭包
3.函数执行形成一个私有的作用链(保护私有变量),进入到私有作用域中,首先变量提升(声明过的变量是私有的),接下来自上而下执行
a.执行的时候遇到一个变量,如果这个变量是私有的那么按照私有处理即可。
function fn(){
    // -> 私有作用域
    // -> 变量提升 var a;(私有变量)
    console.log(a) => // undefined
    var a =12 
    console.log(a) => // 12
}
fn()
console.log(a)  =>// not defined
// ->闭包机制:私有作用域保护里边的私有变量不受外界的干扰

b. 如果当前这个变量不是私有的,我们需要向她的上级作用域进行查找,如果上级也没有,则继续向上查找,一直找到
    window全局作用域为止,我们把这种查找机制叫做作用链
   b.1:如果上级作用域有这个变量,我们当前操作的是上级作用域中的变量(我们在当前作用域把值改了,相当于
       把上级作用域中的这个值给改了。)
   b.2: 如果上级作用域没有这个变量(找window也没有)
   b.3:变量= 值:相当于给window设置了一个属性,后在操作window下就有了
   b.4: alert(变量)想要输出这个变量会报错

function fn(){
    console.log(a) =>// not definde 私有和全局都没有
    A = 12 //  => window.A =12 
    console.log(A) // => 12 
}      
fn()
console.log(A)  // =>12 

1.3、只对等号左边的进行变量提升

1. = :赋值、左边的是变量右边的是值

// ->声明 
var num;
//开辟空间地址存储字符串然后赋值给fn
// function关键字的在变量提升阶段把声明和定义都完成了
function fn(){
    console.log(a)
    var a = 10;
    console.log(a)
}
// 然后代码自上而下执行
num  => undefined
fn  => 函数本身
num = 13; =>//变量提升阶段已经完成了声明了,此处不再需要var,但是没有定义过需要重新赋值
// => 遇到创建fn代码直接跳过,在提升阶段声明和定义已经都做过了
fn() ; // 执行会开辟一个私有作用域,然后开始变量提升var a; 然后代码自上而下执行 

2.匿名函数:函数表达式(把函数当作一个值赋给变量或者其他内容)
var fn // -> 变量提升 undefined
var fn = function(){}
console.log(fn) -> 函数本身

2.1、只对等号左边的进行变量提升,右边是值不会提前声明什么;
2.2、真是项目中应用这个原理,我们创建函数的时候可以使用函数表达式
    2.2.1、因为只能对= 号左边的进行提升,所以变量提升完成后,当前的函数只是声明了没有定义,
    想要执行函数只能放在赋值的代码之后(放在前边执行相当于undefined执行,会报错)
    2.2.2、这样能让我们的代码逻辑更加严谨,以后想要知道一个函数做了什么功能只需要向上查找定义的部分即可

1.4、不管条件是否成立都要进行变量提升

1.不管条件是否成立,判断体中出现 var / function 都会进行变量提升
2.但是在最新浏览器中 function 声明的变量只能提前声明不能定义了(前提函数是在判断体中)

console.log(num)  // undefined
console.log(fn)  // undefined
if(1==1){
    console.log(num)  // undefined
    console.log(fn)   // 函数本身

    var num =12 
    function fn(){}

    console.log(num)  // 12
    console.log(fn)  // 函数本身

}
console.log(fn) // 函数本身(因为fn是全局的)

3.代码执行到条件的地方
4.[条件不成立] 进入不到判断体,赋值的代码执行不了,此时之前声明的变量或者函数依然是 undefined
5.[条件成立] 进入条件判断体的第一件事是不是代码执行而是把之前变量提升没有定义的函数定义了(进入条件判断体当中函数就定义了)
6.老版本浏览器不管条件是否成立都会进行变量提升(和新版本不一样的地方是 新版本function 只是声明,老版本function 是声明加定义)

function fn(){
    // 变量提升 var num;
    return function(){
    }
    var num =100
}
函数体重的 return 后边的代码就不会执行了,但是还会进行变量提升。

1.5、变量提升重名的情况

1.在变量提升阶段,如果名字重复了,不会重新进行声明,但是会重新定义,(后面赋的值会把前面的值替换掉)

// -> 变量提升 fn = aaafff111 (aaafff222,aaafff333,aaafff444)
fn() // ->4
function fn(){console.log(1)}
fn() //->4
funciton fn(){console.log(2)}
fn() //->4

var fn = 13 // ->fn=13

fn() // ->13 不能执行,报错 后边不会再执行
function fn(){console.log(3)}
fn()
function fn(){console.log(4)}
fn()

猜你喜欢

转载自blog.csdn.net/cxz792116/article/details/81220349