成为前端牛马第十三天 —— JS基础部分汇总

一. 数据类型概述

        1. 变量

                变量是储存数据的容器,声明关键字有 let var ,以及常量生成关键字 const


      let age; //声明变量但不赋值,相当于创建一个名为age的容器
      let age1 = 18;

         变量提升情况

                使用 var 关键字声明变量时,会产生变量提升,所以我们必须先声明再使用变量,或者使用 let 关键字声明。

/* 2.变量提升情况 var关键字 先声明后使用*/
      console.log(num); //undefined
      var num = 10;
      /* 相当于
            var num;
            console.log(num);
            num = 10 
      */

      // 报错:ReferenceError 引用类型错误

        2. 基本数据类型

                String | Number | Boolean | undefined | null

        3. 引用数据类型

                Array | Object | Function

        4. 数据类型的转换

                4.1 显式转换

                        4.1.1 字符串 布尔类型转数字类型

                                方法有 Number() | parseInt() | parseFloat()

/* 一.转数字类型 Number语法 */
      /* 1.字符串转数字 */
         var a = "123";
         var b = Number(a);
         console.log(typeof a, typeof b);
      //   string number

      /* 2.null转数字 会转换成0*/
         var a = null;
         var b = Number(a);
         console.log(typeof a, typeof b, b);
      //object number 0

      /* 3.undefined转数字 会转换成NaN,非数字,本质还是数字类型*/
         var a = undefined;
         var b = Number(a);
         console.log(typeof a, typeof b, b);
      //   undefined number NaN

      /* 4.boolean转数字 true对应1 false对应0 */

      /* 5.小数转换 */
         var a = 123.45;
         var b = Number(a);
         console.log(typeof a, typeof b, b);
      //   number number 123.45

      /* 6.带字母字符串转换 */
         var a = "123abc123";
         var b = Number(a);
         console.log(typeof a, typeof b, b);
      //   string number NaN

      /* 二.parseInt 转换方法,主要转换整数,类似于一个数字一个数字转换,遇到字母或是小数点就停止 */
         var a = 123.45;
         var b = parseInt(a);
         console.log(typeof a, typeof b, b);
      //   number number 123 会省略后面的小数

         var a = "123abc123";
         var b = parseInt(a);
         console.log(typeof a, typeof b, b);
      //   string number 123

      /* 三.parseFloat 转换方法,与parseInt类似,可以保留小数 */
                        4.1.2 布尔类型 数字类型转字符串

                                方法有 String() | toString()

/* 一. 转换为字符串类型 String()写法 任何类型皆可转换 */
         let a = null;
         let b = String(a);
         console.log(typeof a, typeof b, b);
      //   object string null

      /* 二. toString() 写法 具有限制,值为null和undefined时会报错可以看做是方法的调用,null和undefined是不能调用方法的*/
      let a = true;
      let b = a.toString();
      console.log(typeof a, typeof b, b);
      let num = 14;
      console.log(num.toString(16)); //进制转换
      //boolean string true
                        4.1.3 字符串 数字类型转布尔类型
/* 一. 类型转换为布尔值 */
      /* 只有0,'',undefined,null,NaN 这些值会转换成false,其余都是true */
         let a = "";
         let b = Boolean(a);
         console.log(typeof a, typeof b, b);
      //   string boolean false

                4.2 隐式转换

                        浏览器通过符号或数字进行数据类型的自动转换

// 二、隐式转换 (浏览器自动转换)

      // 1) 转字符串类型
      // 任意数据类型和字符串拼接,都会变成字符串类型
      // +  这个加号运算符(加法运算、字符串拼接)
       console.log(10 + 20);// 30
       console.log(10 + "abc");// '10abc'
       console.log(typeof 10 );// 'number'
       console.log(typeof 10  + "abc");// 'numberabc'
       console.log(typeof (10  + "abc"));// 'string'
       console.log(typeof true);//'boolean'
       console.log(typeof (true + ""));//'string'
       console.log(typeof (undefined + ""));//'string'

      // 2) 转数字类型
      // 主要数字字符串使用这个“-”可以隐式转换成数字类型
      // 任何数字减去0都等于其本身
      // 任何数字乘以1都等于其本身
      // -   这个符号号运算符(减法运算、转数字)
       console.log(100 - 60);// 40
       console.log(typeof "100");// 'string'
       console.log(typeof ("100" - 0));// 'number'
       console.log(typeof ("100" * 1));// 'number'

      // 3)两个等于号表示比较值的大小,不比较数据类型
      // ==
      // 0 == false
      // "" == false
      // 1 == true
      console.log(0 == false); // true
      console.log("" == false); // true
      console.log(0 == ""); // true
      console.log(1 == true); // true
      console.log(undefined == false); // false


      // 举例:1 > 2 < 3 这个表达式执行的结果: true
      // 1 > 2  表示 false  隐式转换为0
      // 0 < 3  结果 true

        5. 运算符

                5.1 数学运算符

      // + - * / %

      /* 倒计时转换效果 */
      let time = 1000;
      let hour = parseInt(time / 60);
      let min = time % 60;
      console.log(hour + ":" + min);

      /* 字符串数学运算 */
      console.log(1 + "2" * 3 + 4);
      //非加号的字符串数学运算都带有隐式转换,会转换成数字类型进行运算

      /* 自增自减运算 ++ --*/
      let num = 10;
      console.log(num++); //10 先输出再运算
      console.log(num); //11

      console.log(++num); //11 先运算再输出

                5.2 赋值或逻辑运算符

/* JS的赋值运算符有 = += -= *= /=*/
      /* 比较运算符有 == === != !== */
      console.log(true == 1); //true
      console.log("" == 0); //true
      console.log(undefined == 0); //false

      /* 逻辑运算符 || && ! */
      /* 逻辑或 || 一真全真,全假为假 */
      /* 逻辑与 && 全真为真,一假为假 */

      /* || 的运用  默认值操作*/
      let data = "" || "侬好";
      console.log(data); //'侬好'

      /* && 的运用 */
      let data1 = true && 100; //&& 运算符所有的条件都会执行,有值赋值
      console.log(data1);

二. 字符串

        1.概念

        字符串是一个 JS 内的基本数据类型,在 JS 内用单引号 ' ' 或者双引号 " " 包裹的内容就叫做 字符串。

        2.创建字符串

// 1. 字面量方式创建 字符串
var str1 = 'hello world'
var str2 = "hello world"
console.log(str1)	// hello world
console.log(str2)	// hello world

         使用构造函数创建字符串,是以 new 创建对象的形式,所以字符串会被存放在堆内存,变量str1和str2存放的是地址值,str1==str2 是false,str1===str2 也是false

// 2. 构造函数创建字符串
var str1 = new String('hello world')
var str2 = new String("hello world")
console.log(str1)	// String {"hello world"}
console.log(str2)	// String {"hello world"}

        3.字符串相关方法

/* 字符串常用方法 */
      //1.字符串长度
      const str = "hello";
      console.log(str.length); //5

      //2.字符串拼接
      const str1 = "hello";
      const str2 = "world";
      console.log(str1 + str2); //helloworld

      //3.字符串截取
      const str3 = "hello world";
      console.log(str3.slice(0, 5)); //hello

      //4.字符串查找 indexOf charAt
      const str4 = "hello world";
      console.log(str4.indexOf("h")); //0
      console.log(str4.indexOf("o", 5)); //从第五个字符开始查找o

      //4.1 charAt
      const str41 = "hello";
      console.log(str.charAt(1)); // 输出结果:e
      console.log(str[1]); // 输出结果:e
      console.log(str.charAt(5)); // 输出结果:''
      console.log(str[5]); // 输出结果:undefined
      //4.2 includs
      let str42 = "Hello world!";
      str.includes("o"); // 输出结果:true
      str.includes("e", 2); // 输出结果:false,ongoing第二个字符开始查找e
      //4.3 match 返回包含值与索引的数组,通过点语法输出
      let str43 = "abcdef";
      console.log(str43.match("c").input); // ["c", index: 2, input: "abcdef", groups: undefined]

      //5.字符串替换
      const str5 = "hello world";
      console.log(str5.replace("world", "javascript")); //hello javascript

      //6.字符串分割,生成数组 split substr
      const str6 = "hello world";
      console.log(str6.split(" ")); //(2) ["hello", "world"]
      //正则匹配分割
      const list = "apples,bananas;cherries";
      const fruits = list.split(/[,;]/);
      console.log(fruits); // 输出结果:["apples", "bananas", "cherries"]

      //6.1 substr []
      let str61 = "abcdefg";
      str.substr(1, 6); // 输出结果:"bcdefg"
      str.substr(1); // 输出结果:"bcdefg" 相当于截取[1,str.length-1]
      str.substr(); // 输出结果:"abcdefg" 相当于截取[0,str.length-1]
      str.substr(-1); // 输出结果:"g"
      //6.2 substring [)
      let str62 = "abcdefg";
      str.substring(1, 6); // 输出结果:"bcdef" [1,6)
      str.substring(1); // 输出结果:"bcdefg" [1,str.length-1]
      str.substring(); // 输出结果:"abcdefg" [0,str.length-1]
      str.substring(6, 1); // 输出结果 "bcdef" [1,6)
      str.substring(-1); // 输出结果:"abcdefg"

      //7.字符串拼接
      let str7 = "abc";
      console.log(str7.concat("efg")); //输出结果:"abcefg"
      console.log(str7.concat("efg", "hijk")); //输出结果:"abcefghijk"
      console.log(str7.concat("efg", ...str));
      console.log(str + str7);

      //8.移除左右空格,在input输入框中有运用
      let str8 = "  abcdef  ";
      str8.trim(); // 输出结果:"abcdef"

      //9.字符串的转换 数组转字符串join() 字符串转数组split(',')
      let str91 = "abcdef",
        str92 = 123123123;
      arr = [1, 2, 3];
      console.log(str92.toString()); // "123123123"
      console.log(typeof str2.toString()); //string
      console.log(arr.toString()); //1,2,3
      console.log(arr.toString().split(",")); //split分割逗号,['1','2','3']

      /* //7.字符串转大写
      const str7 = "hello world";
      console.log(str7.toUpperCase()); //HELLO WORLD
      //8.字符串转小写
      const str8 = "HELLO WORLD";
      console.log(str8.toLowerCase()); //hello world */

      /* 补充 */
      //1.判断字符串以什么字符开头及结尾
      let s1 = "Hello world!";
      s1.startsWith("Hello"); // 输出结果:true
      s1.startsWith("Helle"); // 输出结果:false
      s1.startsWith("wo", 6); // 输出结果:true
      s1.endsWith("!"); // 输出结果:true
      s1.endsWith("llo"); // 输出结果:false
      s1.endsWith("llo", 5); // 输出结果:true

三. 数组

        1.概念

                一组有序的数据集合,可以同时存储不同类型的值,并且长度是动态的,可以根据需要随时添加或删除元素。

        2.声明

// 1.字面量创建
let arr1 = [1, 2, 3];
// 2.构造函数创建
let arr2 = new Array(10, 20, 30);
let arr3 = new Array(7);//创建一个长度为7的空数组

        3.访问元素

                数组含有规律的索引,通过从0开始到长度-1的索引值来访问和修改元素

let arr = [1,2,3]

console.log(arr[0]);//1

arr[1]=5

console.log(arr);//[1,5,3]

        4.数组遍历

                利用数组有规律的索引,通过for循环的方式进行数组遍历,能够按需取出数组元素

let arr = [1,2,3];

for(let i = 0 ; i < arr.length ; i++){
    console.log(arr[i])//1,2,3
}

        5.相关方法

/* 数组常用方法 */
      //1.数组添加
      var arr = [1, 2, 3, 4, 5];
      res = arr.push(6);
      console.log(res); //返回添加的数值6
      console.log(arr);
      //1.2 unshift(数据)方法向数组的开头添加一个或更多元素,并返回新的数组长度。
      var arr = [1, 2, 3, 4, 5];
      res = arr.unshift(0);
      console.log(res); //[6]
      console.log(arr); //[0,1,2,3,4,5]

      //2.数组删除 pop() 删除数组最后一个元素
      var arr = [1, 2, 3, 4, 5];
      res = arr.push();
      console.log(res); //[5]
      console.log(arr); //[1,2,3,4]
      //2.1shift()方法,删除数组的第一项,并返回删除的项,原数组改变
      var arr = [1, 2, 3, 4, 5];
      res = arr.shift();
      console.log(res); //[1]
      console.log(arr); //[2,3,4,5]

      //3.数组翻转 reverse()方法用于颠倒数组中元素的顺序。返回值:返回颠倒后的数组,原数组改变
      var arr = [1, 2, 3, 4, 5];
      res = arr.reverse();
      console.log(res); //[5,4,3,2,1]
      console.log(arr); //[5,4,3,2,1]
      //3.1.数组翻转 for循环
      let arr1 = [];
      for (let i = arr.length - 1; i >= 0; i--) {
        arr1.push(arr[i]);
      }
      console.log(arr1);

      //4.数组排序 sort()方法用于对数组的元素进行排序。返回值:返回排序后的数组,原数组改变
      var arr = [1, 3, 2, 5, 4];
      res = arr.sort();
      console.log(res); //[1,2,3,4,5]
      console.log(arr); //[1,2,3,4,5]
      //4.1.数组排序 for循环
      for (let i = 0; i < arr.length; i++) {
        for (let n = i + 1; n < arr.length; n++) {
          if (arr[n] > arr[i]) {
            let temp = arr[i];
            arr[i] = arr[n];
            arr[n] = temp;
          }
        }
      }
      console.log(arr); //[5,4,3,2,1]

      //5.数组截取 slice(start,end)方法可从已有的数组中返回选定的元素。返回值:返回截取后的数组,原数组不改变
      var arr = [1, 2, 3, 4, 5];
      res = arr.slice(1, 3);
      console.log(res); //[2,3]
      console.log(arr); //[1,2,3,4,5]
      //5.1.数组截取 splice(开始的索引,结束的索引,添加的元素) 截取从开始到结束的元素,并添加元素,返回被删除的元素
      var arr = [10, 60, 8, 56, 48, 75];
      res = arr.splice(1, 2, 100, 200);
      console.log(arr); //[10, 100, 200, 56, 48, 75]
      console.log(res); //[60, 8]

      //6.数组合并concat() 合并数组,返回新数组
      var arr = [10, 60, 80, 50, 40, 70, 10, 40];
      res = arr.concat(10, "测试", 40);
      console.log(arr); //[10, 60, 80, 50, 40, 70, 10, 40]
      console.log(res); //[10, 60, 80, 50, 40, 70, 10, 40, 10, '测试', 40]
      console.log([...arr, "测试"]); //拓展运算符

      //7.数组转字符串 join()把数组中的元素用指定的字符串连接起来  map(item=>{}).join() js转html结构
      var arr = [10, 60, 80, 50, 40, 70, 10, 40];
      res = arr.join("+");
      console.log(arr); //[10, 60, 80, 50, 40, 70, 10, 40]
      console.log(res); //10+60+80+50+40+70+10+40

      //8.数组查找 indexOf(元素,起始索引位置)
      var arr = [10, 60, 80, 50, 40, 70, 10, 40];
      res = arr.indexOf(40, 3);
      console.log(arr);
      console.log(res);

      /* 9.ES6新增 */
      //forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数。
      //item: 数组中正在处理的当前元素。
      //index: 可选,数组中正在处理的当前元素的索引。
      //arr: 可选,forEach() 方法正在操作的数组。
      var arr = [1, 2, 3, 4, 5];
      console.log(arr);
      var res = arr.forEach(function (item, index, arr) {
        console.log(item, index, arr);
      });

      //map() 方法返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
      var arr = [1, 2, 3, 4, 5];
      console.log(arr); //[1, 2, 3, 4, 5]
      var res = arr.map(function (item) {
        return item * 200;
      });
      console.log(res); //[200, 400, 600, 800, 1000]

      //filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
      //注意: filter() 不会对空数组进行检测。
      //注意: filter() 不会改变原始数组。
      var arr = [1, 20, 35, 44, 50];
      console.log(arr); //[1, 20, 35, 44, 50]
      var res = arr.filter(function (item) {
        return item > 40;
      });
      console.log(res); //[44, 50]

      //every 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
      //如果所有元素都通过检测,则返回 true;否则返回 false。
      var arr = [1, 20, 35, 44, 50];
      console.log(arr); //[1, 20, 35, 44, 50]
      var res = arr.every(function (item) {
        return item > 20;
      });
      console.log(res); //false

      //some =>
      //some 方法是用来检测数组中是否含有符合条件的元素
      //如果有,则返回true,否则返回false
      //some 方法不会对空数组进行检测
      //some 方法不会改变原始数组
      var arr = [1, 20, 35, 44, 50];
      console.log(arr); //[1, 20, 35, 44, 50]
      var res = arr.some(function (item) {
        return item > 22;
      });
      console.log(res); //true

      //find()方法
      //find()方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
      //find()方法不会改变原始数组。
      var arr = [1, 20, 35, 44, 50];
      console.log(arr); //[1, 20, 35, 44, 50]
      var res = arr.find(function (item) {
        return item > 22;
      });
      console.log(res); //35

      //reduce =>
      //用于把数组中的所有值相加得到一个值
      //result => 初始值
      //item => 数组中的每一个值
      //result => 每一次相加的结果
      var arr = [1, 20, 35, 44, 50];
      console.log(arr); //[1, 20, 35, 44, 50]
      var res = arr.reduce(function (result, item) {
        return result + item;
      });
      console.log(res); //150

        5.二维数组 

                一个数组内的元素还是数组形式,形如以下的数组,称为二维数组

let arr = [
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
        [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
      ];

                 二维数组的遍历 : 采用双重循环的方式

for (let i = 0; i < arrData.length; i++) {
        for (let j = 0; j < arrData[i].length; j++) {
          return arr[i][j]
        }
      }

                二维数组的动态生成

/* 渲染一个二维数组 */
function getArray(col,row) {
    let arr = new Array(col);
    for (let i = 0; i < col; i++) {
        arr[i] = new Array(row);
        for (let j = 0; j < row; j++) {
            a[i][j]=1
        }
    }
    return arr;
};

四. 对象

        1.概念

                对象:以键值对形式出现的数据集合 {key:value}

        2.声明方式

// 1.字面量创建
let ming= {
	name:"阿明",
	age:22,
};

// 2.构造函数创建
let ming= new Object();
ming.name = "阿明";
ming.age = 22;


        3.访问和添加删除对象属性

                3.1访问对象属性

                        方法一 : 通过.语法访问

let ming= {
	name:"阿明",
	age:22,
};

console.log(ming.name);//阿明

                        方法二 : 通过键名方式  object[key] 

let ming= {
	name:"阿明",
	age:22,
};

console.log(ming[age]);//22

                3.2添加删除对象属性

                        通过.语法添加

let ming= {
	name:"阿明",
	age:22,
};

ming.study='H5';

console.log(ming)
//{name:'阿明',age:22,study:'H5'}

                        通过delect删除

let ming= {
	name:"阿明",
	age:22,
};

delete ming.age;
// 或者 delete ming[age]

console.log(ming)
//{name:'阿明'}

        4.遍历对象

                对象是不能像数组一样使用普通for循环遍历,因为对象的键名多是没有规律的,但是可以通过 for in 这类方法遍历

let ming= {
	name:"阿明",
	age:22,
};

for(let key in ming){
	let value = ming[key];
    console.log(key + ' ' + value);
    //name '阿明'
    //age 22
}

        5.相关方法

//1.Object.entries(obj):返回对象内可枚举键值对组成的数组;
      const obj1 = { a: "1", b: 2 };
      console.log(Object.entries(obj1)); // [ ['a', '1'], ['b', 2] ]

      //2.Object.keys(obj):返回对象内可枚举键组成的数组;
      // 简单数组,数组的keys值为index索引
      var arr = ["a", "b", "c"];
      console.log(Object.keys(arr)); // console: ['0', '1', '2']
      // 简单对象
      const obj2 = { a: 1, b: 2 };
      console.log(Object.keys(obj2)); // [a,b]

      //3.Object.values(obj):返回对象内可枚举值组成的数组;
      // 简单数组,数组的keys值为index索引
      var arr = ["a", "b", "c"];
      console.log(Object.values(arr)); // console: ['a', 'b', 'c']
      // 简单对象
      const obj3 = { a: 1, b: 2 };
      console.log(Object.values(obj3)); // [1,2]

      //5、delete 操作符:用于删除对象的某个属性
      let obj5 = { a: 1, b: 2 };
      // delete obj;	// 不能直接删除对象,这里会报错
      delete obj5.a;
      console.log(obj5); // 输出{b: 2};

      //6、hasOwnProperty():返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键);
      let obj6 = { a: 1, b: 2 };
      console.log(obj6.hasOwnProperty("a")); // true
      console.log(obj6.hasOwnProperty("c")); // false

      //7、in 操作符:返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键);
      let obj7 = { a: 1, b: 2 };
      console.log("a" in obj7); // true
      console.log("c" in obj7); // false

      //8、Object.assign():用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
      let obj8 = { a: 1, b: 2 };
      let obj9 = { c: 3, d: 4 };
      let obj10 = Object.assign(obj8, obj9);
      let obj11 = { ...obj8, ...obj9 };
      console.log(obj10); // {a: 1, b: 2, c: 3, d: 4}
      console.log(obj11);

      //9、Object.defineProperty() :会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
      /*
	obj: 要定义属性的对象。
	prop: 要定义或修改的属性的名称或 Symbol 。
	descriptor: 要定义或修改的属性描述符。
*/
      //Object.defineProperty(obj, prop, descriptor);

      //使用
      const obj = {};
      Object.defineProperty(obj, "property", {
        value: 1, // value值
      });
      //== 等价于 ==
      Object.defineProperty(obj, "property", {
        value: 1, // value值
        configurable: false, // 是否可删除
        enumerable: false, // 是否可遍历
        writable: false, // 是否可修改
      });
      //所以obj不可修改删除遍历操作,除非把上面的三个属性设置为true
      console.log(obj); // { property: 1}
      delete obj.property; // 删除操作,不生效
      console.log(obj); // { property: 1}

      obj.property1 = 23; // 修改操作,不生效
      console.log(obj); // { property: 1}

      for (let i in obj) {
        // 遍历操作,不生效
        console.log(i); // 无打印
      }

五. 函数

        1. 函数概念

                JS 是一门函数式的编程语言,函数是可以重复利用的代码块

        2. 函数声明

                函数名()

               function 函数名(形式参数...){}

                定义变量接收函数 不能在声明之前调用

                const 函数名 = function(){}

         3. 构造函数

                3.1概念

                        构造函数是一种用于构建对象的代码块。用于构建、设计对象的函数,需要使用new来调用,普通函数作用域的this,往往指向window,因为其在全局环境下。构造函数作用域的this,指向构造函数所创建的实例,因为它是由new来调用。this 是指针变量。不同的作用域this指向是不同。

                3.2 内置构造函数

                        String 、Number 、 Boolean 、 Array 、Object 、Date 、Function ...

                        构造函数的命名规范 名称首字母大写。

                3.3 基本使用

                        采用new操作符调用的函数都是构造函数, const sayHi = new Function('')

function Student(name, age) {
        this.name = name;
        this.age = age;
        this.sayHi = function () {
          console.log("侬好");
        };
      }
      const student = new Student("咸鱼茄子煲", 19);
      student.sayHi();
      console.log(student.age);
      console.log(student.name);
      console.log(student);

六. JS语句

/* javascript 语句 */
      //1.判断语句      if else | if (else if) else | switch
      //2.循环语句      for循环 while循环 do while循环

      /* 2.1 for循环 */
      for (初始化; 终止条件; 增量) {
        // 循环体代码
      }
      for (let i = 0; i < 5; i++) {
        console.log(i);
      }

      /* 2.2 while循环 */
      while (条件) {
        // 循环体代码
      }
      let i = 0;
      while (i < 5) {
        console.log(i);
        i++;
      }

      /* 2.3 do while 循环 */
      do {
        // 循环体代码
      } while (条件);

      let j = 0;
      do {
        console.log(j);
        j++;
      } while (j < 5);

七. 原型链

        1.构造函数的原型对象

                在js中,一个特殊的每一个对象(函数也是对象)都有属性叫做原型(prorotype),它指向另一个对象,这个对象(Object.prototype)被称为原型对象, 原型对象是用来共享属性和方法的。

// 原型 prototype :每个构造函数都有的属性,类型是object,也称原型对象,通过原型对象添加自定义方法
      // 构造函数.prototype

      console.log(Array.prototype); //挂载很多方法 push pop

      // arr调用join方法,但arr实例对象没有这个方法,会找到Array构造函数,再找到其原型对象身上的join方法
      let arr = [1, 2, 3];
      let arrStr = arr.join("");
      console.log(arrStr);

      /* 来个栗子 */
      function App() {}
      App.prototype.sayHi = function (params) {
        console.log(this); //指向实例对象,谁调用指向谁
        console.log("你好啊" + params);
      };
      let app = new App();
      app.sayHi("阿明");
      console.log(app.__proto__);

        2.实例对象的隐式原型 

                在js中,每个实例对象都有一个“ __proto__ ”属性,这个__proto__就被称为隐式原型,它与构造函数的原型对象有相互指向的关系,也就是 obj__proto__ === Object.prototype。

八. 深浅拷贝

        1.概念

                拷贝就是复制或是克隆。js的数据类型主要有基本数据类型和引用数据类型,其中基本数据类型存于栈内存,存储在变量的就是实际的元素;而引用数据类型存于堆内存,存储在变量的为指向堆内存的地址值,所以这两种数据类型在拷贝使用中会有不同。

/* 基本数据类型与引用数据类型的存储 */
      //1.基本数据类型:存在栈内存,变量存储元素值
      let width = "100px";
      //2.引用数据类型:存在堆内存,变量存储地址值
      let _obj = {
        height: "100px",
      };

      /* 数据拷贝和地址拷贝 */
      let a = [1, 2, 3];
      let b;
      b = a;
      b[0] = 100;
      console.log(a); //[100,2,3]
      console.log(b); //[100,2,3]

      let c = [1, 2, 3];
      let d = [];
      d[0] = c[0];
      d[0] = 100;
      console.log(c); //[1,2,3]
      console.log(d); //[100]

        数据拷贝主要是元素赋值操作,两个变量互不影响;但地址拷贝不同,赋值变量的是地址值,也就让两个变量都指向同一个地址的引用数据类型,当一个变量改动数据时,另一个变量也回随之改变。

        2.浅拷贝 

                适用于元素为简单数据类型的情况

// 数组内为基本数据类型
      let arr1 = [1, 2, 3];
      // 数组包含引用数据类型
      let arr2 = [1, 2, { x: "50px" }];

      //封装浅拷贝函数
      function simpleCopy(data) {
        //根据data判断要设置的数据类型
        let newData = Array.isArray(data) === true ? [] : {};
        for (const key in data) {
          newData[key] = data[key];
        }
        return newData;
      }

      //数组包含基本数据类型
      let newArr1 = simpleCopy(arr1);
      newArr1[0] = 100;
      console.log(arr1);
      console.log(newArr1); //不会影响原数组元素

      //数组包含引用数据类型
      //浅拷贝的是地址值,也就是arr1[2]和newArr2[2]共同指向同一个对象
      let newArr2 = simpleCopy(arr2);
      newArr2[2].x = "100px";
      console.log(arr2);
      console.log(newArr2); //会将原数组的数据改变

        3.深拷贝

                适用于元素带有引用数据类型的情况

let obj = {
        a: 1,
        b: 2,
        obj: {
          x: 100,
          y: 200,
        },
      };

      let arr = [1, 2, { o: 100, p: 100 }];

      //封装深拷贝函数
      function deepClone(data) {
        if (data && typeof data === "object") {
          //1.根据传入的数据结构创建对应的数据结构
          let newObj = Array.isArray(data) ? [] : {};
          //2.进行循环,如果是普通类型,调用浅拷贝
          for (const key in data) {
            if (data.hasOwnProperty(key)) {
              //3.判断如果是引用数据类型
              if (data[key] && typeof data[key] === "object") {
                //4.将内部的引用数据类型进行递归,也就是剥层,直到简单数据类型的浅拷贝
                newObj[key] = deepClone(data[key]);
              } else {
                newObj[key] = data[key];
              }
            }
          }
          return newObj;
        } else {
          return data;
        }
      }

      let newObj = deepClone(obj);
      newObj.a = 100;
      newObj.obj.x = 1;

      console.log(obj);
      console.log(newObj);

      let newArr = deepClone(arr);
      newArr[0] = 100;
      newArr[2].o = 1;

      console.log(arr);
      console.log(newArr);

 

前者数据的改变不会影响后者

  • 18
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值