JavaScript数据类型

292 阅读3分钟

问:列举三种强制类型转换和两种隐式类型转换?

答:

强制转换: 转换成字符串 用 数据.toString()/String(数据) 转换成数字 用 Number(数据)/parseInt(数据)/parseFloat(数据) 转换成布尔类型 用 Boolean(数据)

隐式转换: +(拼接字符串)/算数运算符+-*/% ++ --/比较运算符== != > < >= <= /逻辑运算符 && ||

引申:运算符优先级:. () [] 高于 ! ++ --高于* / % 高于 + - 高于 >= <= > < 高于 == === != !== 高于 && 高于|| 高于 赋值运算符 = += -= *= /= %=

问:怎么判断两个对象相等?

答:判断两个对象地址相等直接用===/==判断地址即可,但是要判断对象内容是否相等就需要判断对象的所有键值对是否都相等。 代码如下:

const obj1 = { a: 1, b: { c: 4 } };
const obj2 = { a: 1, b: { c: 3 } };
const obj3 = { a: 1, b: { c: 3 } };
function isObjectValueEqual(obj1, obj2) {
//如果两个对象地址相等,那么他们的内容肯定相等
  if (obj1 === obj2) {
    return true;
  }
//如果两个对象的键名数组长度不相等,那么他们的对象内容肯定不相等,可以直接跳出,节约性能
  const arr1 = Object.keys(obj1);
  const arr2 = Object.keys(obj2);
  if (arr1.length !== arr2.length) return false;
//遍历对象,依次判断键值对是否相等
  for (const i in obj1) {
  //如果当前键的值也是对象,则递归判断对象内容
    if (typeof obj1[i] === "object" || typeof obj2[i] === "object") {
      if (!isObjectValueEqual(obj1[i], obj2[i])) {
        return false;
      }
    } else if (obj1[i] !== obj2[i]) return false;
  }
  return true;
}
console.log(isObjectValueEqual(obj1, obj2)); //false
console.log(isObjectValueEqual(obj3, obj2)); //true

引申:for (key in object)/for (value of list) 遍历对象/数组 key/value可以用const定义,来保证对象与数组在遍历中key/value不会被更改,这与for循环不一样,for循环的循环变量i不可以用const定义,因为i一直在改变,而key/value虽然同样一直在改变,但是因为forin/forof每次循环都会生成一个块级作用域来完成key/value的行为,所以每次循环都是定义一个新的变量key/value,所有的key/value之间互不影响,且不会更改

3.

问:多维数组降维的几种方法?

//多维数组
        let arr = [
          [
            [11, 22],
            [33, 99],
          ],
          [44, 55, 66],
        ];

答:

<1>数组字符串化(全部剥皮)

    ```js
    //两种数组转字符串的方法:join()/拼接字符串
    arr += "";
    // arr = arr.join(",");
    // console.log(arr)//11,22,33,99,44,55,66
    console.log(arr); //11,22,33,99,44,55,66
    arr = arr.split(",");
    console.log(arr); //['11', '22', '33', '99', '44', '55', '66']
    ```

<2>some+concat 递归(逐层剥皮,some判断本层是否有皮,有则递归)

function fc(arr) {
//展开运算符剥下一层[],concat剥下一层[]
  arr = [].concat(...arr);
  //判断数组元素是否还有数组,有则递归
  if (
    arr.some((item) => {
      return Array.isArray(item);
    })
  ) {
    arr = fc(arr);
  }
  return arr;
}
console.log(fc(arr)); //[11, 22, 33, 99, 44, 55, 66]

<3>reduce+concat 递归(逐个剥皮,必须要用不返回数组的方法去遍历数组,有则递归)

 function fc(arr) {
   return arr.reduce((pre, item) => {
     return Array.isArray(item) ? pre.concat(fc(item)) : pre.concat(item);
   }, []);
 }

<4>forEach+instanceof 递归(同上)

function fc(arr) {
  let ret = [];
  let toArr = (arr) => {
    arr.forEach((item) => {
      item instanceof Array ? toArr(item) : ret.push(item);
    });
  };
  toArr(arr)
  return ret
}

<5>arr.flat(层数) es10新增降维方法

var arr1 = [1, 2, [3, 4]];
arr1.flat(); // [1, 2, 3, 4]

var arr2 = [1, 2, [3, 4, [5, 6]]];
arr2.flat();// [1, 2, 3, 4, [5, 6]]

var arr3 = [1, 2, [3, 4, [5, 6]]];
arr3.flat(2);// [1, 2, 3, 4, 5, 6]

//使用 Infinity 作为深度,展开任意深度的嵌套数组
arr3.flat(Infinity); // [1, 2, 3, 4, 5, 6]

问:如何判断JavaScript的数据类型?

<1>typeof 数据 简单数据类型里只不能识别null,会返回Object,复杂数据类型里只能识别函数,其余返回Object

<2>通过构造函数判断 <2.1>数据 instanceof 构造函数 判断该构造函数是否在该数据的原型链上,不能用于判断原始数据类型数据,只能判断对象(广义对象(包括数组和函数还有包装类型对象)) <2.2>数据.constructor 直接返回数据的构造函数,可以判断原始数据类型(包装数据类型)

<3>Object.prototype.toString(数据)

通过call实现数据调用Object原型上的toString方法返回数据类型(虽然所有类都继承自Object,但所有类都将继承自Object的toString方法进行了改写)

Object.prototype.toString().call(数据) //[Object 数据类型] Object.prototype.toString().call(数据).slice(8,-1) //数据类型

<4>Array.isArray(数据) 判断是否数组

引申:原型链:实例对象的__proto__属性指向他的构造函数的原型对象,他的构造函数的原型对象的__proto__属性指向Object构造函数的原型对象,Object的__proto__属性不存在,即指向null,函数作为对象,也有自己原型链,函数的__proto__属性指向函数构造函数的原型对象,函数构造函数的原型对象的__proto__属性指向Object,Object不存在__proto__属性,即指向null,可知null是原型链的尽头

5.null与undefined的区别

// 类型判断
console.log(typeof null, typeof undefined); //object undefined  =》typeof null 返回object 是js历史遗留问题
console.log(
  Object.prototype.toString.call(null), //[object Null]
  Object.prototype.toString.call(undefined) //[object Undefined]
);
// 值判断
console.log(Number(null), Number(undefined));// 0 NaN
console.log(Boolean(null), Boolean(undefined));//false false
console.log(null==undefined,null===undefined);//true false
console.log(null==null,null===null)//true true
console.log(undefined == undefined,undefined === undefined);//true true
//各自用处
// 所有变量(包括全局变量(位于全局作用域的函数的return)、局部变量(包括函数形参、对象属性、位于局部作用域的函数的return))都可以用undefined表示未赋值,null专门用来表示对象未赋值(原型链尽头/函数实参为null表示参数不是对象) 

引申:"==="是等同符 ,"=="是等值符,等同符判断数据类型与值是否都相同,是则返回true,否则返回false;等值符判断数据类型是否相同,如果不同,隐式转换为相同类型,再判断值是否相同,相同返回true,否则返回false