JavaScript入门第十九章(JS补充知识点)(完结)

简介: JavaScript入门第十九章(JS补充知识点)(完结)

1.引用类型与值类型区别


  • 引用类型:复杂数据类型,object(Object、Array、Date、RegRex、function)


  • 值类型:基本数据类型,五种:string number boolean undefined null。
  • 1.变量只能访问栈中的空间
  • 2.如果是引用类型(复杂数据类型),则将保存在堆中,而栈中存储的是这个数据的地址。
  • 3.如果是值类型(基本数据类型),则数据保存在栈中(数据比较小,读取比较快捷方便)
  • 4.内存主要有两部分:栈与堆


  <script>
       /* 引用类型:array,obejct    数据存储在堆中,地址存储在栈中
           值类型:string number boolean undefined null 数据存储在栈中
           区别:值类型:栈中存储的是数据,变量赋值时拷贝的是数据,修改拷贝后的数据不会对原数据造成影响
           引用类型:栈中存储的是地址,变量赋值时拷贝的也是地址,修改拷贝后的数据会对原数据造成影响
       */
      // 1.值类型:拷贝的是数据
      var num1 = 10;
      var num2 = num1;          // 将num1的数据拷贝一份保存到num2中
      num2 = 100;
      console.log ( num1, num2 );   // 修改num2不会对num1造成影响
      // 2.引用类型:  拷贝的是地址
      var arr1 = [10,20,30,40,50];
      var arr2 = arr1;          // 将arr1的地址拷贝一份保存到num2中
      arr2[0] = 100;
      console.log ( arr1, arr2 );   // 修改arr2会对arr1造成影响
  </script>


2.共享引用

  • JS中实际对象传值不是真正的引用传值(传地址),而是传递引用的副本(call by sharing):按共享传递


  • 对象赋值的本质是对象引用的副本
  • 保存副本的对象如果是对对象本身进行操作:那么就是引用(操作原对象)
  • 保存副本的对象如果是重新赋值:那么就重新开辟存储空间


  // 1.对象共享传递
    var obj1 = { name: '我是本体' };
    // 2.对象引用(共享)
    var obj2 = obj1;
    var obj3 = obj1;
    // 3.引用的改变效果:如果操作的是对象本身(属性或者方法)那么操作的是原对象obj1,如果把保存引用的变量赋值其他任何类型数据,那么都会重开内存(不影响obj1)
    obj2.name = '我是新本体';  // obj2操作的是obj1本身的对象,所以修改是共用的(不开辟新空间)
    console.log(obj1);          // {name: "我是新本体"}
    obj3 = 1;         // obj3独立开辟内存空间保存1,与obj1和obj2不再有关联
    console.log(obj1);          // {name: "我是新本体"}
  // 共享引用:共享引用是JS中复杂数据类型的本质传递方式而已


3.基本包装类型


  • 本身是基本数据类型,但是在执行代码的过程中,可以调用相关的属性和方法


  • JS中有三种基本包装类型
  • Number
  • String
  • Boolean


 /*
      // 问题:为什么num是一个基本数据类型,可以像对象一样调用方法呢?
      // 基本数据类型
      var num = 10;
      console.log ( typeof num );
    num.toString () ;
      /*
      本质相当于执行了以下代码(JS解释器检测到num调用来toString()方法,所以快速处理了)
      (1) var num = new Number(10);   // 创建对象
      (2) num.toString();       // 调用对象方法
      (3) num = null;         // 删除对象
       */
      // 对象类型
      var num1 = new Number(10);
      /*
        由于num1本身就是对象类型,所以这里可以直接调用,无需转换
      */
      num1.toString();
      console.log ( num1 );
      console.log ( typeof num1 ); // object
      var str = '111';
    str.toString();
      /*
      (1)var str = new String('111');
      (2)str.toString();
      (3)str = null;
       */
      var bol = true;
      bol.toString();
      /*
      (1) var bol = new Boolean(true);
      (2) bol.toString();
      (3) bol = null();
       */
  /*
    基本包装类型和引用类型(new Number()/String()/Boolear()的区别
    1.new产生的对象是长期占用内存,直到脚本结束
    2.基本包装类型属于后台瞬发,用完就销毁了对象:对象 = null
    所以:String/Number/Boolean,我们在开发中都是使用基本包装类型
  */


4.数组去重


数组去重:将数组中重复的元素去掉


  • JS数组没有删除具体元素的删除(只能删掉值,删不掉元素的索引),可以使用另外一个结构来进行存储
  • 新数组
  • 新对象
  • JS数组虽然本质可以删除第一个和最后一个元素,可以利用这一特性,交换当前重复的元素到最后,然后进行删除(pop() 或者length--)


  <script>
        var arr = [20, 66, 88, 25, 66, 90, 88, 50]; // [20,25,66,88,90,50]
        //1.排序法
        // // 1.1 对数组排序
        // arr.sort(function(a,b){
        //     return a-b;
        // });
        // console.log(arr);
        // // 1.2 声明空数组存储去重后的数组
        // var newArr = [];
        // //1.3 遍历arr,检查arr[i]与arr[i+1]是否相等
        // for(var i = 0;i<arr.length;i++){
        //     if(arr[i] != arr[i+1]){
        //         newArr[newArr.length] = arr[i];
        //     };
        // };
        // console.log(newArr);
        // 2.假设成立法
        // // 2.1 声明空数组存储去重后的数组
        // var newArr = [];
        // // 2.2 遍历arr,检查arr[i]在不在newArr中
        // for (var i = 0; i < arr.length; i++) {
        //     // 假设成立法 : 某种操作结果只有两种清空。布尔类型存储两种情况。
        //     // 1.声明
        //     var single = true; // 假设不在
        //     // 2.遍历newArr检查 只要与arr[i]相等
        //     for (var j = 0;j<newArr.length;j++) {
        //         if (arr[i] == newArr[j]) {
        //             single = false;
        //             break; // 只要发现重复元素,后面没有必要比较
        //         };
        //     };
        //     // 3. 根据结果实现需求
        //     if (single) {
        //         newArr[newArr.length] = arr[i];
        //     };
        // };
        // console.log(newArr);
        // 3.indexOf
        // // 2.1 声明空数组存储去重后的数组
        // var newArr = [];
        // // 2.2 遍历arr,检查arr[i]在不在newArr中
        // for (var i = 0; i < arr.length; i++) {
        //     if(newArr.indexOf(arr[i]) == -1){ // 不在
        //         newArr.push(arr[i]);
        //     }
        // };
        // console.log(newArr);
        // 4.对象法
        var arr = [20, 66, 88, 25, 66, 90, 88, 50];
        /* 核心思路:利用对象的属性名不能重复
            对象的取值赋值特点
                取值 : 存在,取值。 不存在,取undefined
                赋值 : 存在,修改。 不存在,动态添加
        1.声明空对象 : 检查数组元素是否重复 (元素作为属性名,检查对象有没有这个属性)
        2.声明空数组 :存储去重后的数组
        3.遍历arr,检查arr[i]是否重复
         */
         var obj = {};
         var newArr = [];
         for (var i = 0;i<arr.length;i++) {
            // 检查对象有没有 arr[i] 这个属性?
            if (obj[arr[i]] == undefined) { // 未重复 
                newArr.push(arr[i]);
                obj[arr[i]] = 1; // 这里赋值目的是为了下一次取值,不是undefined
            }
         };
         console.log(newArr);
        // 5.重复元素自我交换删除法
        /*
          核心思路:判定元素在数组中查到的位置是否是自身(元素是一定能找到的)
            * 如果是自身:说明当前元素还没有重复
            * 如果不是自身:说明当前元素在前面已经存在过:交换最后一个元素,然后把最后一个删除
          步骤:
          1.遍历数组的每一个元素
          2.判定当前遍历的元素在当前数组中存在的位置,判定位置是否是当当前自己的位置
          2.1.是自己位置,说明前面没有重复,忽略
          2.2.不是自己位置,说明前面已经存在:
            2.2.1交换最后一个元素过来
            2.2.2然后删除
            2.2.3最后一个元素有可能已经与前面重复了,为了不跳过当前新交换的元素,重新从当前元素开始检索  
        */
        arr = [1,1,2,3,5,0,1];
        for (var i = 0; i < arr.length; i++) {
            / /判定当前元素在数组中找出的位置
            if (arr.indexOf(arr[i]) != i) {
                // 说明不是自己:前面已经存在过
                // 交换最后一个元素过来(因为最后一个可以删除
                var temp = arr[i];
                arr[i] = arr[arr.length - 1];
                arr[arr.length - 1] = temp;
                // 删除最后一个元素:两种方式都可以
                // arr.pop();
                arr.length--;
                // 最后一个元素有可能已经与前面重复了,所以为了保证安全,被交换过来的元素还要重新经受考验
                i--;
            }
        }
        // 注意:以上方式会改变数组中原来元素的顺序位置
    </script>
相关文章
|
2月前
|
机器学习/深度学习 人工智能 JavaScript
js和JavaScript
js和JavaScript
21 4
|
10天前
|
存储 JavaScript 前端开发
【JavaScript技术专栏】JavaScript基础入门:变量、数据类型与运算符
【4月更文挑战第30天】本文介绍了JavaScript的基础知识,包括变量(var、let、const)、数据类型(Number、String、Boolean、Undefined、Null及Object、Array)和运算符(算术、赋值、比较、逻辑)。通过实例展示了如何声明变量、操作数据类型以及使用运算符执行数学和逻辑运算。了解这些基础知识对初学者至关重要,是进阶学习JavaScript的关键。
|
6天前
|
JavaScript 前端开发 开发者
JavaScript基础入门之浏览器控制台调试输出
本文章是对小白学习js的初级教程,也是我对自己学习经验的一种总结,文章大多采用使用案例加讲解,带动学习的方式.因为我们的天性总是喜欢有及时反馈的事物,但是学习是一个慢长的事情,而有结果的回应,才会更好的促进自己去学习,主要是对于javascript学习中的输出,有个大体上的了解,同时通过教学能够更好的使用浏览器来方便我们去学习和运行代码,也是对自己进行笔记整理,对抓住信息关键点的一种提高.
|
8天前
|
JSON JavaScript 前端开发
使用JavaScript和XLSX.js将数据导出为Excel文件
使用JavaScript和XLSX.js将数据导出为Excel文件
20 0
|
10天前
|
JavaScript 前端开发 开发工具
【JavaScript 技术专栏】Node.js 基础与实战
【4月更文挑战第30天】本文介绍了Node.js的基础及应用,包括事件驱动的非阻塞I/O、单线程模型和模块系统。内容涵盖Node.js的安装配置、核心模块(如http、fs、path)及实战应用,如Web服务器、文件操作和实时通信。文章还讨论了Node.js的优劣势、与其他技术的结合,并通过案例分析展示项目实施流程。总结来说,Node.js是高效后端开发工具,适合构建高并发应用,其广阔的应用前景值得开发者探索。
|
10天前
|
JSON JavaScript 前端开发
深入探讨javascript的流程控制与分支结构,以及js的函数
深入探讨javascript的流程控制与分支结构,以及js的函数
|
14天前
|
前端开发 JavaScript
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
前端 富文本编辑器原理——从javascript、html、css开始入门
26 0
前端 富文本编辑器原理——从javascript、html、css开始入门(二)
|
14天前
|
前端开发 JavaScript 索引
前端 富文本编辑器原理——从javascript、html、css开始入门(一)
前端 富文本编辑器原理——从javascript、html、css开始入门
36 0
|
17天前
|
JavaScript 前端开发 算法
< JavaScript小技巧:如何优雅的用【一行代码 】实现Js中的常用功能 >
在开发中,采用简洁的语法和结构,遵循一致的命名规范,具有良好的代码组织和注释,能很好的提高代码的质量。可读性:易于阅读和理解。清晰的命名、简洁的语法和良好的代码结构可以使代码的意图更加明确,降低理解代码的难度,提高代码的可读性。可维护性:易于维护。当代码逻辑清晰、结构简洁时,开发者可以更快速地定位和修复bug,进行功能扩展或修改。同时,可读性高的代码也有助于后续的代码重构和优化。可扩展性:更具有扩展性和灵活性。清晰的代码结构和简洁的代码风格使得添加新功能、修改现有功能或扩展代码更加容易。
< JavaScript小技巧:如何优雅的用【一行代码 】实现Js中的常用功能 >
|
17天前
|
JavaScript 前端开发
js开发:请解释this关键字在JavaScript中的用法。
【4月更文挑战第23天】JavaScript的this关键字根据执行环境指向不同对象:全局中指向全局对象(如window),普通函数中默认指向全局对象,作为方法调用时指向调用对象;构造函数中指向新实例,箭头函数继承所在上下文的this。可通过call、apply、bind方法显式改变this指向。
8 1