尚硅谷js高级基础部分

基于尚硅谷的尚硅谷JavaScript高级教程提供笔记撰写,加入一些个人理解

github源码
如果你想下载本文可以前往我的博客 博客地址

数据类型的分类和判断

主要问题

分类
基本(值)类型
  • Number ----- 任意数值 -------- typeof
  • String ----- 任意字符串 ------ typeof
  • Boolean ---- true/false ----- typeof
  • undefined — undefined ----- typeof/===
  • null -------- null ---------- ===
对象(引用)类型
  • Object –任意对象— typeof/instanceof
  • Array —特别的对象类型(下标/内部数据有序)— instanceof
  • Function –特别的对象类型(可执行)– typeo
数据类型判断
  • typeof:

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

    例如:

    var a = 3
    console.log(typeof a==='number');//输出true
    

    可以区别: 数值, 字符串, 布尔值, undefined, function

    不能区别: null与对象, 一般对象与数组

    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引擎如何管理内存
  1. 内存生命周期
  • 分配需要的内存空间,得到使用权
  • 存储数据,可以反复操作
  • 释放当前的内存空间
  1. 释放内存

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

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

    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请求回调函数(后面讲解)
    • 生命周期回调函数(后面讲解)
匿名函数自调用:
 (function (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();

补充

分号问题

  1. js一条语句的后面可以不加分号

  2. 是否加分号是编码风格问题, 没有应该不应该,只有你自己喜欢不喜欢

  3. 在下面2种情况下不加分号会有问题

    小括号开头的前一条语句

    中方括号开头的前一条语句

    解决办法: 在行首加分号

 // 情形一: 小括号开头的前一条语句
  var a = 3
  ;(function () {
  })()
  /*
  错误理解: 将3看成是函数调用
    var a = 3(function () {
    })
   */
  // 情形二: 中方括号开头的前一条语句
  var b = 4
  ;[1, 3, 5].forEach(function (item) {
    console.log(item)
  })
  /*
    错误理解:
    b= 4[5].forEach(function(e){
    console.log(e)
    })*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值