JS 基础总结

分类

基本(值)类型

  • Number —– 任意数值 ——– typeof
  • String —– 任意字符串 —— typeof
  • Boolean —- true/false —– typeof
  • undefined — undefined —– typeof/===
  • null ——– null ———- ===

对象(引用)类型

  • Object –任意对象— typeof/instanceof
  • Array —特别的对象类型(下标/内部数据有序)— instanceof
  • Function –特别的对象类型(可执行)– typeof

数据类型判断

typeof

typeof返回值是数据类型的字符串表达

例如:

var a = 3
console.log(typeof a==='number');//输出true
  • 可以区别: 数值, 字符串, 布尔值, undefined, function
  • 不能区别: null 与 object, object 与数组
  • typeof 判断 null 与数组 均为 object

instanceof

专门用来判断对象数据的类型: Object, Array 与 Function

===

可以判断: undefined和null

简单来说,=== 只能判断出只有一个值的数据类型

undefined与null的区别?

undefined代表定义了但没有赋值

null代表赋值了, 只是值为null

// 1. undefined与null的区别?
   var a
   console.log(a);//undefinde
   a = null
   console.log(a);//null

什么时候给变量赋值为null呢?

变量将指向一个对象, 但对象此时还没有确定

让变量指向的对象成为垃圾对象

   // 2. 什么时候给变量赋值为null呢?
   //初始
   var b = null//初始赋值为null,表明将要赋值为对象
   //中间
   b = ['atguigu', 12]//确定对象就赋值
   //结束
   b = null// 让b指向的对象成为垃圾对象(被垃圾回收器回收)

严格区别变量类型与数据类型?(平常不会严格区分)

  • 数据类型:
    • 基本类型
    • 对象类型

js的变量本身是没有类型的, 变量的类型实际上是变量内存中数据的类型

  • 变量类型:(变量内存值的类型)
  • 基本类型: 保存基本类型数据的变量
  • 引用类型: 保存对象地址值的变量

数据,变量, 内存的理解

什么是数据?

在内存中可读的, 可传递,可运算的保存了特定信息的'东东',本质就是0101二进制

一切皆数据, 函数也是数据

在内存中的所有操作的目标: 数据

  • 算术运算
  • 逻辑运算
  • 赋值
  • 调用函数传参

什么是变量?

  • 值可以变化的量, 由变量名与变量值组成
  • 一个变量对应一块小内存, 变量名用来查找到内存, 变量值就是内存中保存的内容

什么是内存?

  • 内存条通电后产生的存储空间(临时的) 产生和死亡: 内存条(集成电路板)==>通电==>产生一定容量的存储空间==>存储各种数据==>断电==>内存全部消失 内存的空间是临时的, 而硬盘的空间是持久的
  • 一块内存包含2个方面的数据 内部存储的数据(一般数据/地址数据) 内存地址值
  • 内存空间的分类 栈空间: 全局变量和局部变量 堆空间: 对象

内存,数据, 变量三者之间的关系

  • 内存是容器, 用来存储不同数据
  • 变量是内存的标识, 通过变量我们可以操作(读/写)内存中的数据

赋值与内存的问题

问题: var a = xxx, a内存中到底保存的是什么?

   var a = 3 // 保存3
   a = function () {
   }//保存地址值
   var b = 'abc'
   a = b // b保存的数据'abc'
   b = []
   a = b // b保存的地址值

xxx是一个基本数据,保存的就是这个数据

xxx是一个对象,保存的是对象的地址值

xxx是一个变量,保存的是xxx的内存内容(可能是基本数据,也可能是地址值)

关于引用变量赋值问题

n个引用变量指向同一个对象, 通过一个引用变量修改对象内部数据, 其他所有引用变量也看得见

    var obj1 = { name: 'Tom' }
    var obj2 = obj1
    obj2.age = 12
    console.log(obj1.age);//12
    
    function fn(obj) {
      obj.name = 'Bob'
    }
    fn(obj1)
    console.log(obj2.name);//Bob

2个引用变量指向同一个对象,让一个引用变量指向另一个对象, 另一个引用变量还是指向原来的对象

    var a = { age: 12 }
    var b = a
    a = { name: 'Jack', age: 13 }
    console.log(b.age, a.name, a.age);//12 Jack 13

/*
 这里记住一点,是将实参a赋值给形参obj,即 obj=a,此时他们指向同一对象。执行obj={age:15},obj指向发生改变,而a指向未发生改变
*/
    function fn2(obj) {
      obj = { age: 15 }
    }
    fn2(a)
    console.log(a.age);//13

在js调用函数时传递变量参数时, 是值传递还是引用传递

对这个问题可以有着两种理解,第一种是理解为两个都是值传递,只是这个值可以是基本数据,也可以是地址数据。第二种则是把传递的地址值看作是引用传递,不过一般来说都当做是值传递。

    var a = 3
    function fn(a) {
      a = a + 1
    }
    fn(a)// 传的不是a,而是3这个值
    console.log(a);// 3
/* 
执行到:fn(a);先读到a是3,把a的值传给形参a,形参a去加1,输出为4。
实参a还是实参a,所以最后输出a仍然是3。这里是基本值传递。
*/
    function fn2(obj) {
      console.log(obj.name);
    }
    var obj = { name: 'Tom' }
    fn2(obj)
/*
执行到:fn2(obj);把obj中的内容(不是把{name:‘tom'}传递给形参obj,
是把obj的地址值传给形参obj,只是地址值指向的是 {name:‘tom'})传递给形参obj。
这里是地址值传递。
*/

JS引擎如何管理内存

内存生命周期

  • 分配需要的内存空间,得到使用权
  • 存储数据,可以反复操作
  • 释放当前的内存空间

释放内存

为执行函数分配的栈空间内存(局部变量): 函数执行完自动释放

存储对象的堆空间内存(对象): 当内存没有引用指向时, 对象成为垃圾对象, 垃圾回收器后面就会回收释放此内存

    var a = 3
    var obj = {}// 执行到这里,一共开辟了3个内存空间
    obj = null //  obj指向的对象内存空间被释放,obj不释放,手动释放
    
    function fn() {
      var b = {} // 只有函数被执行的时候才会开辟内存空间,即 fn()调用
    }
    fn()
    /*
    fn()执行完,b被自动释放,b所指向的对象在后面的某个时刻由垃圾回收器回收
    */

对象的理解和使用

什么是对象

  • 代表现实中的某个事物, 是该事物在编程中的抽象
  • 多个数据的集合体(封装体)
  • 用于保存多个数据的容器

为什么要用对象?

便于对多个数据进行统一管理

对象的组成

属性

  • 代表现实事物的状态数据
  • 由属性名和属性值组成
  • 属性名都是字符串类型, 属性值是任意类型

属性的分类

  • 一般属性 : 属性值不是function 描述对象的状态
  • 方法 : 属性值为function的属性 描述对象的行为

特别的对象

  • 数组: 属性名是0,1,2,3之类的索引
  • 函数: 可以执行的

    如何操作内部属性(方法)

    obj.属性名 obj[‘属性名'] 一般不用,但通用

什么时候必须使用[‘属性名']的方式?

  • 属性名不是合法的标识名(包含特殊字符:- 空格等)
  • 属性名不确定
// 创建对象
   var p = {}
   /*情形一: 属性名不是合法的标识名*/
   /*需求: 添加一个属性: content-type: text/json */
   p.content-type = 'text/json' //不正确
   p['content-type'] = 'text/json'
   /*情形二: 属性名不确定*/
   var prop = 'xxx'  // 我们想让这个值(xxx)做属性名
   var value = 123
   p.prop = value  //不正确  这么写的属性名是prop
   p[prop] = value
   console.log(p['content-type'], p[prop])

函数的理解和使用

什么是函数?

  • 具有实现特定功能的n条语句的封装体
  • 只有函数是可执行的, 其它类型的数据是不可执行的
  • 函数也是对象

    为什么要用函数?

  • 提高复用性
  • 便于阅读交流

    如何定义函数?

  • 函数声明
  • 表达式
fn1()// 输出fn1
fn2()// 声明前调用,输出undefined
//函数声明
function fn1() {
  console.log('fn1');
}
//表达式
var fn2 = function () {
  console.log('fn2');
}

区别:js中的变量提升

  • 函数声明可以在声明前调用
  • 表达式不能在声明前调用,输出为undefined

如何调用(执行)函数?

  • test():直接调用
  • new test():new调用
  • obj.test():对象调用
  • test.call/apply(obj):临时让test成为obj的方法进行调用
  var obj = {}
  function test2() {
    this.xxx = 'atguigu'
  }
  test2.call(obj) // 可以让一个函数成为指定任意对象的方法进行调用
//test2.apply(obj)
  console.log(obj.xxx) // atguigu

call和apply改变了函数test2中的this指向,将函数test2中的this指向从window改变,指向call和apply传入的对象(后面有讲到this的指向问题)

函数也是对象

instanceof Object===true

函数有属性: prototype

函数有方法: call()/apply()

可以添加新的属性/方法

函数的3种不同角色

  • 一般函数 : 直接调用
  • 构造函数 : 通过new调用
  • 对象 : 通过.调用内部的属性/方法

    回调函数的理解

什么函数才是回调函数?

  • 你定义的
  • 你没有调用
  • 但它最终执行了(在一定条件下或某个时刻)

常用的回调函数

  • dom事件回调函数
  • 定时器回调函数
  • ajax请求回调函数(后面讲解)
  • 生命周期回调函数(后面讲解)

匿名函数自调用:

(  (i) {
   var a = 4
   function fn() {
     console.log('fn ', i+a)// 7
   }
   fn()
 })(3)

专业术语为: IIFE (Immediately Invoked Function Expression) 立即调用函数表达式

作用:

  • 隐藏内部实现
  • 不污染外部命名空间
  • 编码js模块

this是什么?

任何函数本质上都是通过某个对象来调用的,没有直接指定就是window 所有函数内部都有一个变量this 它的值是调用函数的当前对象

如何确定this的值?

test():window

obj.test():obj

new test():新建的对象

test.call(obj):obj

前置知识:

本质上任何函数在执行时都是通过某个对象调用的

function Person(color) {
      console.log(this)
      this.color = color;
      this.getColor = function () {
        console.log(this)
        return this.color;
      };
      this.setColor = function (color) {
        console.log(this)
        this.color = color;
      };
    }

    Person("red"); //this是谁? window

    var p = new Person("yello"); //this是谁? p

    p.getColor(); //this是谁? p

    var obj = {};
    p.setColor.call(obj, "black"); //this是谁? obj

    var test = p.setColor;
    test(); //this是谁? window

    function fun1() {
      function fun2() {
        console.log(this);
      }

      fun2(); //this是谁? window
    }
    fun1();