JS基础知识深入总结

本文深入探讨JavaScript基础知识,包括数据类型的分类与判断,如基本数据类型和对象数据类型的特点,以及typeof、valueOf()和toString()的用法。详细解析数据类型间的比较规则,并通过实例解析对象和函数的理解与使用。此外,还涉及内存管理、变量、内存、对象和函数在内存中的表示和交互,以及函数节流与防抖等高级概念。
摘要由CSDN通过智能技术生成

本系列将从以下专题去总结:

  1. JS基础知识深入总结
  2. 对象高级
  3. 函数高级
  4. 事件对象与事件机制

暂时会对以上四个专题去总结,现在开始JS之旅的第一部分:JS基础知识深入总结。下图是我这篇的大纲。
js基础大纲前端学习大纲

话在前面:我一直都认为,在互联网学习的大环境下,网路学习资源很多,但这些博客等仅仅是一个向导,一个跳板,真正学习知识还是需要线下,需要书籍。
另外,如有错误,请留言或私信。一起成长,谢谢。

1.1 数据类型的分类和判断

1.1.1 数据类型的分类

  • 基本(值)类型 [primitive values]
基本类型 类型的值 检测方法
Number 可以任意数值 用typeof检测结果为number
String 可以任意字符串 用typeof检测结果为string
Boolean 只有true/false 用typeof检测结果为boolean
undefined 只有undefined 用typeof检测数据类型和‘===’(全等符号)
null 只有null ‘===’(全等符号)
Symbol 通过Symbol()得到,值可任意 用typeof可检测结果为symbol
  • 对象(引用)类型 [reference values]
对象类型 描述 检测方法
Object 可以任意对象 可以用typeof/instanceof检测数据类型
Array 一种特别的对象(有数值下标,而且内部数据是有序的。一般的对象内部的数据是无序的,比如你一个对象中有name和age,他们是无序的。) instanceof
Function 一种特别的对象(可以去执行的对象,内部包含可运行的代码。一个普通的对象可以执行吗?不能。)另外,对象是存储一些数据的,当然函数也是存储一些代码数据。 typeof
Date 时间对象 instanceof
RegExp 正则对象 instanceof

1.1.2 基本/对象数据类型特点比较

基本数据类型 对象类型
基本类型的值是不可变的 引用类型的值是可变的
基本类型的比较是它们的值的比较 引用类型的比较是引用(指针指向)的比较
基本类型的变量是存放在栈内存(Stack)里的 引用类型的值是保存在堆内存(Heap)中的对象(Object)

1.1.3 数据类型的判断

  • typeof
    注1:用typeof判断返回数据类型的字符串(小写)表达。比如:typeof ‘hello’ 结果是 string
    注2:用typeof来测试有以下七种输出结果:number string boolean object function symol undefined。 因此typeof不能去判断出nullobject,因为用typeof去判断null会输出object
    注3:所有的任何对象,用typeof测试数据类型都是object。因此,typeof不能去判断出objectarray

  • ===(全等符号)
    注1:只可以判断undefined 和 null 因为这两种基本类型的值是唯一的,即可用全等符比较。

  • instanceof
    注1:A instanceof B 翻译就是B的实例对象是A 吗? 判断对象的具体类型(到底是对象类型中的Object Array Function Date RegExp的哪一个具体的类型),返回一个Boolean值。

  • 借调法:Object.prototype.toString.call()
    注1:这种方法只可以检测出内置类型(引擎定义好的,自定义的不行),这种方法是相对而言更加安全。Object Date String Number RegExp Boolean Array Math Window等这些内置类型。

以上说明都有案例在面试题里

1.1.3 四个常见问题

  • 问题1:undefined与报错(not defined)的区别?
    对象.属性:属性不存在则返回undefined
    访问变量:变量不存在则报错,xx is not defined
    var obj={
          name:'lvya' };
    console.log(obj.age); //undefined
    console.log(age);  //报错,age is not defined
    
    从这个点再去看一个简单的例子:
    function Person(name,age,price) {
         
      this.name = name
      this.age = age
      this.price=price
      setName=function (name) {
         
        this.name=name;
      }
    }
    
    var p1 = new Person('LV',18,'10w')
    console.log(p1.price); // 10w
    
    根据上面这个例子,问个问题。请问访问p1.price先找啥?后找啥?通过啥来找?(问题问的不好,直接看答案吧)
    An:p1.price先找p1后找 price 。 p1是一个全局变量哦,这个全局变量本身存在栈内存中,它的值是一个地址值,指向new Person 出来的对象。怎么找呢?先找p1是沿着作用域找的,后找price是沿着原型链找的。这就是联系,从另外一个方面细看问题。可能这样看问题,你就可以把原型链和作用域可以联系起来思考其他问题。

串联知识点:请你讲讲什么是原型链和作用域链?
我们从a.b这个简单的表达式就可以看出原型链和作用域链。(a正如上例的p1)第一步先找a!a是一个变量,通过作用域链去查找,一层一层往外找,一直找到最外层的window,还没找到那就会报错,a is not defined。 找到a这个变量,它的值有两种情况:基本数据类型和对象类型。
如果是基本数据类型(除了undefined和null)会使用包装类,生成属性。如果是undefined和null就会报错,显示不能读一个undefined或null的属性。
如果是对象类型,这就是对象.属性的方式,开始在对象自身查找,找不到沿着原型链去找。原型链也找不到的时候,那么就会输出undefined

原型与原型链图解

  • 问题2:undefined与null的区别?
    undefined代表定义未赋值
    nulll定义并赋值了, 只是值为null

        var a;
        console.log(a);  // undefined
        a = null;
        console.log(a); // null
    

    使用Object.prototype.toString.call()形式可以具体打印类型来区别undefined和null。
    如果值是undefined,返回“[object Undefined]”。
    如果这个值为null,则返回“[object Null]”。

  • 问题3:什么时候给变量赋值为null 呢?
    初始赋值, 表明这个变量我要去赋值为对象
    结束前, 这个对象不再使用时,让对象成为垃圾对象(被垃圾回收器回收)

        //起始
        var b = null   // 初始赋值为null, 表明变量b将要赋值为对象类型
        //确定赋值为对象
        b = ['lvya', 12]
        //结束,当这个变量用不到时
        b = null  // 让b指向的对象成为垃圾对象(被垃圾回收器回收)
        // b = 2  //当然让b=2也可以,但不常使用
    
  • 问题4:变量类型与数据类型一样吗?
    数据的类型:包含基本数据类型和对象类型
    变量的类型(实则是变量内存值的类型) JS弱类型语言,变量本身是无类型的。包含基本类型: 保存的就是基本类型的数据(比如:数字1,字符串‘hello lvya’,布尔值false等)和引用类型: 保存的是地址值,这个地址值去指向某个对象。

1.1.4 一张图看懂JavaScript各类型的关系

JavaScript各类型的关系

1.1.5 谈谈valueOf( ) 与 toString( )

toString()valueOf() 都是在Object.prototype里面定义.

  1. toString()
    表示的含义是把这个对象表示成字符串形式, 并且返回这个字符串形式.
    首先,在Object.prototype中它对toString()方法的默认实现是"[object Object]"。
    验证一下:

       var p={
         };   
       console.log(p.toString());   //[object Object]   去Object.prototype的去找(输出他的默认实现)
       function Person(){
         
       }
       var p1=new Person();
       console.log(p1.toString());  //[object Object]  去Object.prototype的去找(输出他的默认实现)
    

    再看一下可以在自己的对象或者原型上对 toString() 进行覆写(重写, override)。这时访问这个对象的toString()方法时,就会沿着原型链上查找,刚好在自身对象上就找到了toString(),这个时候就不再去找原型链上的顶端Object.prototype的默认的toString()啦,便实现了对象的toString()的重写。
    验证一下:

       var p = {
         
       toString: function (){
         
         return "100";
         }
       };
       //100  这个时候就会在首先在P对象上找toString()方法,这个时候就是对toString方法的重写
       console.log(p.toString());  
    

    再举一个重写的栗子:

      var date = new Date();
      console.log(date.toString());   
      //Fri Jan 18 2019 21:13:44 GMT+0800 (中国标准时间)
      /*从输出结果可知,Date这个构造函数的原型其实是有toString()方法的,
      说明JS引擎已经在Date原型对象中重写了toString()方法,
      故不会在Object.prototype中找*/
      console.log(Date.prototype);  //发现确实有toString()方法
    
      var n = new Number(1);
      console.log(n.toString());  //1(字符串)
      /*
      同理:这就是说明他们在js引擎内置的包装对象,说白了,就是内部已经给Number对象上重写了
      toString()方法。这个方法刚好就是将数字转为字符串*/
    
  2. valueOf()
    应该返回这个对象表示的基本类型的值!在Object.prototype.valueOf 中找到, 默认返回的是this。当需要在对象上重写valueOf()时,应该是返回一个基本数据类型的值。
    先看一个默认返回的值的情况。(也就是说它是去这个对象的原型链的顶端Object.prototype.valueOf 找的valueOf方法 )

    function Person(){
         
      }
     var p1 = new Person();
     console.log(p1.valueOf() == p1);  //true  
    

    对返回结果的说明:这个时候p1.valueOf是在Object.prototype.valueOf找到的,返回值默认this。此时this就是p1的这个对象。故结果返回true
    现在看一下重写valueOf后的情况

    var p = {
         
          toString: function (){
         
            return "100";
          },
          valueOf : function (){
         
            return 1;
          }
        };
        console.log(p.toString());  //100(字符串)   
        //还来不及去Object.prototype.valueOf 其本身就有了toString方法 故当然读本身对象的toString()方法
        console.log(p.valueOf());  //1(number数据类型) 
        //同理,没去Object.prototype.valueOf找 而是找其本身的valueOf方法
    

    我们再来验证JS引擎对那些内置对象有去重写toString()valueOf()呢?

    var n = new Number(100);
    console.log(n.valueOf());  //100 (number类型)
    
    var s = new String("abc");
    console.log(s.valueOf());  //abc (string类型)
    
    var regExp = /abc/gi;
    console.log(regExp.valueOf() === regExp);  //true 
    //说明这个时候正则对象上没有valueOf,是在Object.prototype.valueOf找的,返回this,this指的就是regExp正则对象。
    

    结论:在JS中, 只有基本类型中那几个包装类型进行了重写, 返回的是具体的基本类型的值, 其他的类型都没有重写,是去对象原型链的顶层Object.prototype.valueOf去找的。

1.1.6 数据类型间的比较

了解完valueOf()toSting()方法后,其实他们就是对象与基本数据类型的比较的基础。我们数据类型,分为基本数据类型和对象类型两种,故在数据类型比较中,只会有三种情况:

  1. 基本数据类型间的比较
  2. 对象类型间的比较
  3. 基本数据类型与对象类型间的比较

基本数据类型间的比较

规则:如果类型相同,则直接比较; 如果类型不同, 都去转成number类型再去比较
三个特殊点:1. undefined == null 2. 0undefined, 0null都不等 3. 如果有两个 NaN 参与比较,则总是不等的。

总结:都是基本数据类型,但当类型不同时,转为number类型的规律如下:

基本类型中非number类型 转为number类型
undefined ‘12a’ ‘abc’ ‘\’ Nan
'' ' ' '\t' '0' null false 0
true ‘1’ 1
‘12’ 12

我们来看看ECMA官方文档对转number类型的说明:
转number类型
另外 再补充一点,在JS世界里,只有五种转Boolean类型是false的:0 Nan undefined null "" false。其他的转Boolean值都是true
我们再来看看ECMA官方文档对转Boolean类型的说明:
转Boolean类型
所以,从这里我们就可以发现其实原文的ECMA官方文档就是很棒的学习资料,已经帮你整理的很完备了。多去翻翻这些官方文档的资料很有帮助。

例子1:属于基本类型间的比较,而且都是基本类型中的number类型,相同类型直接比较。

var a=1;
var b=1;
console.log(a == b); //true  

console.log("0" == "");   //false  
//都是相同的string类型,不用转,直接用字符串比较

例子2:属于基本类型间的比较,但是其具体的类型不同,需要转为number类型再去比较。

console.log(true == "true");  //false  相应转为number类型去比较:1与Nan比较
console.log(0 == "0");   //true  相应转为number类型去比较:0与0比较
console.log(0 == "");   //true   相应转为number类型去比较:0与0比较

console.log(undefined == null);  //true  Nan与0比较??特殊

例子3:属于三大特殊点

console.log(undefined == null);  //true  
console.
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值