JS面试题--JavaScript数据类型

news2024/11/17 0:07:00

数据类型

1.JavaScript有哪些数据类型,它们的区别?

JavaScript共有八种数据类型,分别是 Undefined、Null、Boolean、Number、String、Object、Symbol、BigInt。

其中 Symbol 和 BigInt 是ES6 中新增的数据类型:
● Symbol 代表创建后独一无二且不可变的数据类型,它主要是为了解决可能出现的全局变量冲突的问题。
● BigInt 是一种数字类型的数据,它可以表示任意精度格式的整数,使用 BigInt 可以安全地存储和操作大整数,即使这个数已经超出了 Number 能够表示的安全整数范围。

这些数据可以分为原始数据类型和引用数据类型:
● 栈:原始数据类型(Undefined、Null、Boolean、Number、String、Symbol、BigInt)
● 堆:引用数据类型(对象、数组和函数)

基本数据类型的修改实际上是新申请一块内存地址,将这个指针指向新的内存地址。使用const定义变量,实际上相当于定义了一个指针常量,指向固定的地址不能被修改。

引用类型修改时相当于前拷贝,内存地址不发生变化

引用类型的赋值其实是对象保存在栈区地址指针的赋值,因此两个变量指向同一个对象,任何操作都会相互影响

var a ={};
var b = a;
a.name = 'Mary';
console.log(a.name); //'Mary'
console.log(b.name);//'Mary'
 
b.age = 22;
console.log(b.age); //22
console.log(a.age); //22
console,.log(a==b);  //true

在这里插入图片描述
两种类型的区别在于存储位置的不同:
● 原始数据类型直接存储在栈(stack)中的简单数据段,占据空间小、大小固定,属于被频繁使用数据,所以放入栈中存储;
● 引用数据类型存储在堆(heap)中的对象,占据空间大、大小不固定。如果存储在栈中,将会影响程序运行的性能;引用数据类型在栈中存储了指针,该指针指向堆中该实体的起始地址。当解释器寻找引用值时,会首先检索其在栈中的地址,取得地址后从堆中获得实体。

堆和栈的概念存在于数据结构和操作系统内存中,在数据结构中:
● 在数据结构中,栈中数据的存取方式为先进后出。
● 堆是一个优先队列,是按优先级来进行排序的,优先级可以按照大小来规定。

在操作系统中,内存被分为栈区和堆区:
● 栈区内存由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。
● 堆区内存一般由开发着分配释放,若开发者不释放,程序结束时可能由垃圾回收机制回收。

2. 数据类型检测的方式有哪些

(1)typeof

console.log(typeof 2);               // number
console.log(typeof true);            // boolean
console.log(typeof 'str');           // string
console.log(typeof []);              // object    
console.log(typeof function(){});    // function
console.log(typeof {});              // object
console.log(typeof undefined);       // undefined
console.log(typeof null);            // object

其中数组、对象、null都会被判断为object,其他判断都正确。

(2)instanceof

instanceof可以正确判断对象的类型,其内部运行机制是判断在其原型链中能否找到该类型的原型。

console.log(2 instanceof Number);                    // false
console.log(true instanceof Boolean);                // false 
console.log('str' instanceof String);                // false 
 
console.log([] instanceof Array);                    // true
console.log(function(){} instanceof Function);       // true
console.log({} instanceof Object);                   // true

instanceof只能正确判断引用数据类型,而不能判断基本数据类型。

(3) constructor

console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true

constructor有两个作用,一是判断数据的类型,二是对象实例通过 constrcutor 对象访问它的构造函数。需要注意,如果创建一个对象来改变它的原型,constructor就不能用来判断数据类型了:

function Fn(){};
 
Fn.prototype = new Array();
 
var f = new Fn();
 
console.log(f.constructor===Fn);    // false
console.log(f.constructor===Array); // true

(4)Object.prototype.toString.call()

Object.prototype.toString.call() 使用 Object 对象的原型方法 toString 来判断数据类型:

var a = Object.prototype.toString;
 
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));

同样是检测对象obj调用toString方法,obj.toString()的结果和Object.prototype.toString.call(obj)的结果不一样

  console.log(function () {}.toString());
  //function () {}
  

这是因为toString是Object的原型方法,而Array、function等类型作为Object的实例,都重写了toString方法。不同的对象类型调用toString方法时,根据原型链的知识,调用的是对应的重写之后的toString方法(function类型返回内容为函数体的字符串,Array类型返回元素组成的字符串…),而不会去调用Object上原型toString方法(返回对象的具体类型),所以采用obj.toString()不能得到其对象类型,只能将obj转换为字符串类型;因此,在想要得到对象的具体类型时,应该调用Object原型上的toString方法。

3. 判断数组的方式有哪些

● 通过Object.prototype.toString.call()做判断

 <script>
      function fn() {
        console.log("11");
      }
      console.log(Object.prototype.toString.call(fn)); //”[object Function]”);//”[object Function]”
	
      var obj = [1, 2, 3];
      //通过Object.prototype.toString.call()做判断
      console.log(Object.prototype.toString.call(obj).slice(8, -1) === "Array"); //true
      //通过原型链做判断
      console.log(obj.__proto__ === Array.prototype);//true
      //通过ES6的Array.isArray()做判断
      console.log(Array.isArray(obj));//true
      //通过instanceof做判断
      console.log(obj instanceof Array);//true
      //通过Array.prototype.isPrototypeOf
      console.log(Array.prototype.isPrototypeOf(obj));//true
    </script>

4. null和undefined区别

1、概念

undefined 表示未定义,就是应该有值但是还没有赋值,连null的值都没有赋予

null 代表空值,空引用。

2、区别

  1. null 和 undefined 虽然值的结果是相等的,但是其所代表的语义是完全不一样的(==是相等的)。

undefined 代表了某个变量完全不存在,在内存中完全能不存在这个标识符所指向的地址;

null 代表了内存中是存在这个变量的,只是我在某些情况下需要把这个变量原本的值给覆盖了,将它设置为一个空。

  1. null 转为数值是 0 ; undefined 转为数值是 NAN(not a number)。

  2. null 通过 typeof 判断类型的时候结果的输出是 object ; 而 undefined 的类型是 undefined 。

那么为什么 typeof null 是 object ?

null 和 undefined 都是js语言的基础数据类型, 都是原始值类型,但是 typeof null 是 object ,是因为不同的对象在底层都表现为二进制,在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型,null 的二进制全部都为 0 ,前三位自然也是 0 ,所以执行 typeof 值会返回 object 。

  1. null 是 js 语言的关键字,是不允许用户用来作为标识符声明变量的,但是 undefined 可以,undefined 不是关键字。

在 node 环境中,我们声明的 undefined 会将原本的 undefined 覆盖的,但是在浏览器环境中不会,是因为浏览器中的 undefined 是直接被使用 Object.defineProperty 定义在了全局对象 window 上,默认就已经被配置成为了:值不可修改并且不可以被重新进行配置。

3、null 和 undefined分别在实际项目中出现的场景有哪些

1、 undefined

a. 变量被声明了,但是没有被赋值;

b. 调用函数的时候,应该给函数传参却没有给函数传这个参数打印出来就是 undefined;

c. 访问一个对象中没有的属性;

d. 函数没有返回值时,默认就会返回undefined。

2、 null

a.作为对象原型链的终点出现;

b.当我们访问一个不存在的dom节点的时候。

5. typeof null 的结果是什么,为什么?

typeof null 的结果是Object。

javascript中不同对象在底层都表示为二进制,而javascript 中把二进制前三位都为0的判断为object类型,而null的二进制表示全都是0,自然前三位也是0,所以执行typeof时会返回’object’

在 JavaScript 第一个版本中,所有值都存储在 32 位的单元中,每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储值的真实数据。类型标签存储在每个单元的低位中,共有五种数据类型:

000: object   - 当前存储的数据指向一个对象。
  1: int      - 当前存储的数据是一个 31 位的有符号整数。
010: double   - 当前存储的数据指向一个双精度的浮点数。
100: string   - 当前存储的数据指向一个字符串。
110: boolean  - 当前存储的数据是布尔值。

如果最低位是 1,则类型标签标志位的长度只有一位;如果最低位是 0,则类型标签标志位的长度占三位,为存储其他四种数据类型提供了额外两个 bit 的长度。

有两种特殊数据类型:
● undefined的值是 (-2)30(一个超出整数范围的数字);
● null 的值是机器码 NULL 指针(null 指针的值全是 0)

那也就是说null的类型标签也是000,和Object的类型标签一样,所以会被判定为Object。

6. intanceof 操作符的实现原理及实现

instanceof 运算符用于判断构造函数的 prototype 属性是否出现在对象的原型链中的任何位置。

function myInstanceof(left, right) {
  // 获取对象的原型
  let proto = Object.getPrototypeOf(left)
  // 获取构造函数的 prototype 对象
  let prototype = right.prototype; 
 
  // 判断构造函数的 prototype 对象是否在对象的原型链上
  while (true) {
    if (!proto) return false;
    if (proto === prototype) return true;
    // 如果没有找到,就继续从其原型上找,Object.getPrototypeOf方法用来获取指定对象的原型
    proto = Object.getPrototypeOf(proto);
  }
}

7. 为什么0.1+0.2 ! == 0.3,如何让其相等

<script>
      let n1 = 0.1,
        n2 = 0.2;
      console.log(n1 + n2); // 0.30000000000000004
      console.log((n1 + n2).toFixed(2)); // 注意,toFixed为四舍五入
    </script>

计算机是通过二进制的方式存储数据的,所以计算机计算0.1+0.2的时候,实际上是计算的两个数的二进制的和。0.1的二进制是0.0001100110011001100…(1100循环),0.2的二进制是:0.00110011001100…(1100循环),这两个数的二进制都是无限循环的数。那JavaScript是如何处理无限循环的二进制小数呢?

一般我们认为数字包括整数和小数,但是在 JavaScript 中只有一种数字类型:Number,它的实现遵循IEEE 754标准,使用64位固定长度来表示,也就是标准的double双精度浮点数。在二进制科学表示法中,双精度浮点数的小数部分最多只能保留52位,再加上前面的1,其实就是保留53位有效数字,剩余的需要舍去,遵从“0舍1入”的原则。

根据这个原则,0.1和0.2的二进制数相加,再转化为十进制数就是:0.30000000000000004。

下面看一下双精度数是如何保存的:

● 第一部分(蓝色):用来存储符号位(sign),用来区分正负数,0表示正数,占用1位
● 第二部分(绿色):用来存储指数(exponent),占用11位
● 第三部分(红色):用来存储小数(fraction),占用52位

一个直接的解决方法就是设置一个误差范围,通常称为“机器精度”。对JavaScript来说,这个值通常为2-52,在ES6中,提供了Number.EPSILON属性,而它的值就是2-52,只要判断0.1+0.2-0.3是否小于Number.EPSILON,如果小于,就可以判断为0.1+0.2 ===0.3

function numberepsilon(arg1,arg2){                   
  return Math.abs(arg1 - arg2) < Number.EPSILON;        
}        

console.log(numberepsilon(0.1 + 0.2, 0.3)); // true

8. 如何获取安全的 undefined 值?

因为 undefined 是一个标识符,所以可以被当作变量来使用和赋值,但是这样会影响 undefined 的正常判断。表达式 void ___ 没有返回值,因此返回结果是 undefined。void 并不改变表达式的结果,只是让表达式不返回值。因此可以用 void 0 来获得 undefined。

9. typeof NaN 的结果是什么?

NaN 指“不是一个数字”(not a number),NaN 是一个“警戒值”(sentinel value,有特殊用途的常规值),用于指出数字类型中的错误情况,即“执行数学运算没有成功,这是失败后返回的结果

typeof NaN; // "number"

NaN 是一个特殊值,它和自身不相等,是唯一一个非自反(自反,reflexive,即 x === x 不成立)的值。而 NaN !== NaN 为 true。

10.isNaN 和 Number.isNaN 函数的区别

NaN
NaN意指“not a number“,是一个“警戒值”,用于指出数字类型中的错误情况。
typeof NaN的返回值是”number“。
NaN是一个特殊值,它与自身不相等,是唯一一个非自反的值。即 NaN === NaN 返回false,NaN !== NaN 返回true。
因此,我们不能简单地通过 == 或者=== 运算符来判断数值是否非法数值,我们需要 isNaN() 或者 Number.isNaN() 两个函数进行判断。

typeof NaN   // "number"
NaN === NaN  // false
NaN !== NaN  // true

isNaN()
isNaN() 函数接收一个参数x,用来检查x是否非数字值。
isNaN() 函数接收参数x之后,会先把参数x转换为数字类型,任何非数字类型的值都会被强制转换为NaN,再做判断。
因此,isNaN() 函数的参数是NaN或者其他能够被转换为NaN的值时,结果都会返回true,其他值的情况下返回false。
故,isNaN() 函数会影响NaN的准确判断。

isNaN(null)   // false  Number(null) => 0
isNaN(undefined)   // true  Number(undefined) => NaN
isNaN(1)      // false
isNaN(' ')    // false  Number(' ') => 0
isNaN('1')    // false  Number('1') => 1
isNaN('abc')  // true   Number('abc') => NaN
isNaN('NaN')  // true   Number('NaN') => NaN
isNaN([])     // false  Number([]) => 0
isNaN([1])    // false  Number([1]) => 1
isNaN(['a'])  // true   Number(['a']) => NaN
isNaN({})	  // true   Number({}) => NaN
isNaN('2021/5/22')  // true  Number('2021/5/21') => NaN
isNaN(0 / 0)  // true
isNaN(NaN)    // true

Number.isNaN()
Number.isNaN() 函数也是接收一个参数x,判断x是否非数字值。
Number.isNaN() 函数在接收参数x之后,会首先判断参数x是否为数字类型,如果是数字类型则继续判断是否NaN。
因此,Number.isNaN() 相比全局函数 isNaN() 更为精准,只有在参数x本身为NaN的情况下才会返回true。

// 只有参数本身为NaN结果才为true
Number.isNaN(NaN)    // true
Number.isNaN(Number.NaN)   // true
Number.isNaN(0 / 0)  // true

// 以下在全局isNaN()函数的结果都为true,在Number.isNaN()结果都为false
isNaN(undefined)   // false
isNaN('abc')  // false
isNaN('NaN')  // false
isNaN(['a'])  // false
isNaN({})	  // false
isNaN('2021/5/22')  // false

// 以下仍然为false
isNaN(null)   // false
isNaN(1)      // false
isNaN(' ')    // false
isNaN('1')    // false
isNaN([])     // false
isNaN([1])    // false

11. == 操作符的强制类型转换规则?

在这里插入图片描述
对于 == 来说,如果对比双方的类型不一样,就会进行类型转换。假如对比 x 和 y 是否相同,就会进行如下判断流程:

  1. 首先会判断两者类型是否相同,相同的话就比较两者的大小;
  2. 类型不相同的话,就会进行类型转换;
  3. 会先判断是否在对比 null 和 undefined,是的话就会返回 true
  4. 判断两者类型是否为 string 和 number,是的话就会将字符串转换为 number
1 == '1'1 ==  1
  1. 判断其中一方是否为 boolean,是的话就会把 boolean 转为 number 再进行判断
'1' == true'1' ==  11  ==  1
  1. 判断其中一方是否为 object 且另一方为 string、number 或者 symbol,是的话就会把 object 转为原始类型再进行判断
'1' == { name: 'js' }'1' == '[object Object]'  

12. 其他值到字符串的转换规则?

● Null 和 Undefined 类型 ,null 转换为 “null”,undefined 转换为 “undefined”,
● Boolean 类型,true 转换为 “true”,false 转换为 “false”。
● Number 类型的值直接转换,不过那些极小和极大的数字会使用指数形式。
● Symbol 类型的值直接转换,但是只允许显式强制类型转换,使用隐式强制类型转换会产生错误。
● 对普通对象来说,除非自行定义 toString() 方法,否则会调用 toString()(Object.prototype.toString())来返回内部属性 [[Class]] 的值,如"[object Object]"。如果对象有自己的 toString() 方法,字符串化时就会调用该方法并使用其返回值。

13. 其他值到数字值的转换规则?

● Undefined 类型的值转换为 NaN。
● Null 类型的值转换为 0。
● Boolean 类型的值,true 转换为 1,false 转换为 0。
● String 类型的值转换如同使用 Number() 函数进行转换,如果包含非数字值则转换为 NaN,空字符串为 0。
● Symbol 类型的值不能转换为数字,会报错。
● 对象(包括数组)会首先被转换为相应的基本类型值,如果返回的是非数字的基本类型值,则再遵循以上规则将其强制转换为数字。

为了将值转换为相应的基本类型值,抽象操作 ToPrimitive 会首先(通过内部操作 DefaultValue)检查该值是否有valueOf()方法。如果有并且返回基本类型值,就使用该值进行强制类型转换。如果没有就使用 toString() 的返回值(如果存在)来进行强制类型转换。

如果 valueOf() 和 toString() 均不返回基本类型值,会产生 TypeError 错误。

14. 其他值到布尔类型的值的转换规则?

以下这些是假值:
• undefined
• null
• false
• +0、-0 和 NaN
• “”

假值的布尔强制类型转换结果为 false。从逻辑上说,假值列表以外的都应该是真值。

15. || 和 && 操作符的返回值?

|| 和 && 首先会对第一个操作数执行条件判断,如果其不是布尔值就先强制转换为布尔类型,然后再执行条件判断。

● 对于 || 来说,如果条件判断结果为 true 就返回第一个操作数的值,如果为 false 就返回第二个操作数的值。
● && 则相反,如果条件判断结果为 true 就返回第二个操作数的值,如果为 false 就返回第一个操作数的值。

|| 和 && 返回它们其中一个操作数的值,而非条件判断的结果

在js中&&运算符优先级大于||

a || b:

如果a是true,那么b不管是true还是false,都返回true。因此不用判断b了,这个时候刚好判断到a,因此返回a。
如果a是false,那么就要判断b,如果b是true,那么返回true,如果b是false,返回false,其实不就是返回b了吗。

a && b:

如果a是false,那么b不管是true还是false,都返回false,因此不用判断b了,这个时候刚好判断到a,因此返回a。
如果a是true,那么就要在判断b,和刚刚一样,不管b是true是false,都返回b。

      let a = true;
      let b = true;
      console.log(a && b);
      console.log(a || b);
 <script>
      console.log(false || 1); //1
      console.log(false || 0); //0
      console.log(true || 0); //true
      console.log(true || 1); true
      console.log(true == 1); //true
      console.log(true == 0); //false

      //   console.log(false && 1); //false
      //   console.log(false && 0); //false
      //   console.log(true && 0); //0
      //   console.log(true && 1); //1
      //   console.log(true == 1); //true
      //   console.log(true == 0); //false
    </script>

16. Object.is() 与比较操作符 “=”、“” 的区别?

● 使用双等号()进行相等判断时,如果两边的类型不一致,则会进行强制类型转化后再进行比较。
● 使用三等号(
=)进行相等判断时,如果两边的类型不一致时,不会做强制类型准换,直接返回 false。
● 使用 Object.is 来进行相等判断时,一般情况下和三等号的判断相同,它处理了一些特殊的情况,比如 -0 和 +0 不再相等,两个 NaN 是相等的。

      console.log(-0 === +0); //true
      console.log(NaN === NaN); //false

      console.log(Object.is(-0, +0)); //false
      console.log(Object.is(NaN, +NaN));//true

17. 什么是 JavaScript 中的包装类型?

在 JavaScript 中,基本类型是没有属性和方法的,但是为了便于操作基本类型的值,在调用基本类型的属性或方法时 JavaScript 会在后台隐式地将基本类型的值转换为对象,如:

const a = "abc";
a.length; // 3
a.toUpperCase(); // "ABC"

在访问’abc’.length时,JavaScript 将’abc’在后台转换成String(‘abc’),然后再访问其length属性。

JavaScript也可以使用Object函数显式地将基本类型转换为包装类型:

var a = 'abc'
Object(a) // String {"abc"}

也可以使用valueOf方法将包装类型倒转成基本类型:

var a = 'abc'
var b = Object(a)
var c = b.valueOf() // 'abc'

看看如下代码会打印出什么:

var a = new Boolean( false );
if (!a) {
	console.log( "Oops" ); // never runs
}

包装类返回的是一个对象

答案是什么都不会打印,因为虽然包裹的基本类型是false,但是false被包裹成包装类型后就成了对象,所以其非值为false,所以循环体中的内容不会运行。

18. JavaScript 中如何进行隐式类型转换?

首先要介绍ToPrimitive方法,这是 JavaScript 中每个值隐含的自带的方法,用来将值 (无论是基本类型值还是对象)转换为基本类型值。如果值为基本类型,则直接返回值本身;如果值为对象,其看起来大概是这样:

/**
* @obj 需要转换的对象
* @type 期望的结果类型
*/
ToPrimitive(obj,type)

type的值为number或者string。
(1)当type为number时规则如下:
● 调用obj的valueOf方法,如果为原始值,则返回,否则下一步;
● 调用obj的toString方法,后续同上;
● 抛出TypeError 异常。
(2)当type为string时规则如下:
● 调用obj的toString方法,如果为原始值,则返回,否则下一步;
● 调用obj的valueOf方法,后续同上;
● 抛出TypeError 异常。

可以看出两者的主要区别在于调用toString和valueOf的先后顺序。默认情况下:
● 如果对象为 Date 对象,则type默认为string;
● 其他情况下,type默认为number。
总结上面的规则,对于 Date 以外的对象,转换为基本类型的大概规则可以概括为一个函数:

var objToNumber = value => Number(value.valueOf().toString())
objToNumber([]) === 0
objToNumber({}) === NaN

而 JavaScript 中的隐式类型转换主要发生在+、-、*、/以及==、>、<这些运算符之间。而这些运算符只能操作基本类型值,所以在进行这些运算前的第一步就是将两边的值用ToPrimitive转换成基本类型,再进行操作。

以下是基本类型的值在不同操作符的情况下隐式转换的规则 (对于对象,其会被ToPrimitive转换成基本类型,所以最终还是要应用基本类型转换规则):

  1. +操作符+操作符的两边有至少一个string类型变量时,两边的变量都会被隐式转换为字符串;其他情况下两边的变量都会被转换为数字。
1 + '23' // '123'
 1 + false // 1 
 1 + Symbol() // Uncaught TypeError: Cannot convert a Symbol value to a number
 '1' + false // '1false'
 false + true // 1
  1. -、*、\操作符NaN也是一个数字
1 * '23' // 23
 1 * false // 0
 1 / 'aa' // NaN
  1. 对于==操作符
    操作符两边的值都尽量转成number:
3 == true // false, 3 转为number为3,true转为number为1
'0' == false //true, '0'转为number为0,false转为number为0
'0' == 0 // '0'转为number为0
  1. 对于<和>比较符
'ca' < 'bd' // false
'a' < 'b' // true

其他情况下,转换为数字再比较:

'12' < 13 // true
false > -1 // true

以上说的是基本类型的隐式转换,而对象会被ToPrimitive转换为基本类型再进行转换:

var a = {}
a > 2 // false

其对比过程如下:

a.valueOf() // {}, 上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步
a.toString() // "[object Object]",现在是一个字符串了
Number(a.toString()) // NaN,根据上面 < 和 > 操作符的规则,要转换成数字
NaN > 2 //false,得出比较结果

又比如:

var a = {name:'Jack'}
var b = {age: 18}
a + b // "[object Object][object Object]"

运算过程如下:

a.valueOf() // {},上面提到过,ToPrimitive默认type为number,所以先valueOf,结果还是个对象,下一步
a.toString() // "[object Object]"
b.valueOf() // 同理
b.toString() // "[object Object]"
a + b // "[object Object][object Object]"

19. + 操作符什么时候用于字符串的拼接?

根据 ES5 规范,如果某个操作数是字符串或者能够通过以下步骤转换为字符串的话,+ 将进行拼接操作。如果其中一个操作数是对象(包括数组),则首先对其调用 ToPrimitive 抽象操作,该抽象操作再调用 [[DefaultValue]],以数字作为上下文。如果不能转换为字符串,则会将其转换为数字类型来进行计算。

简单来说就是,如果 + 的其中一个操作数是字符串(或者通过以上步骤最终得到字符串),则执行字符串拼接,否则执行数字加法。

那么对于除了加法的运算符来说,只要其中一方是数字,那么另一方就会被转为数字。

20. 为什么会有BigInt的提案?

JavaScript中Number.MAX_SAFE_INTEGER表示最⼤安全数字,计算结果是9007199254740991,即在这个数范围内不会出现精度丢失(⼩数除外)。但是⼀旦超过这个范围,js就会出现计算不准确的情况,这在⼤数计算的时候不得不依靠⼀些第三⽅库进⾏解决,因此官⽅提出了BigInt来解决此问题。

21. object.assign和扩展运算法是深拷贝还是浅拷贝,两者区别

扩展运算符:

let outObj = {
  inObj: {a: 1, b: 2}
}
let newObj = {...outObj}
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}

Object.assign():

let outObj = {
  inObj: {a: 1, b: 2}
}
let newObj = Object.assign({}, outObj)
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}

可以看到,两者都是浅拷贝。
● Object.assign()方法接收的第一个参数作为目标对象,后面的所有参数作为源对象。然后把所有的源对象合并到目标对象中。它会修改了一个对象,因此会触发 ES6 setter。
● 扩展操作符(…)使用它时,数组或对象中的每一个值都会被拷贝到一个新的数组或对象中。它不复制继承的属性或类的属性,但是它会复制ES6的 symbols 属性。

22. 如何判断一个对象是空对象

使用JSON自带的.stringify方法来判断:

if(Json.stringify(Obj) == '{}' ){
    console.log('空对象');
}

使用ES6新增的方法Object.keys()来判断:

if(Object.keys(Obj).length < 0){
    console.log('空对象');
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/113652.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux系统基础——程序和进程

代码&#xff0c;程序&#xff0c;进程 特此说明: 刘超的趣谈linux操作系统是比较重要的参考资料&#xff0c;本文大部分内容和图片来源于这个专栏。 1 实验环境 运行一个demo&#xff0c;主要功能是主进程通过系统调用fork一个新的进程&#xff0c;子进程功能是加载二进制文件…

背包模型~

背包模型 概述 ​ 最长上升子序列&#xff1a;序列DP&#xff08;相邻两个被选择的有关系&#xff09; 背包问题&#xff1a;组合DP&#xff0c;在全局的考虑之下最小 f[i][j]&#xff1a;i 表示搞了多少&#xff0c;j 表示限制 集合&#xff1a;所有仅仅从前 i 个物品当…

论文推荐:CCNet用于语义分割的交叉注意力

CCNet&#xff0c; Transformer递归交叉自注意力&#xff0c;比非局部神经网络更有效。华中科技大学、地平线、ReLER 和伊利诺伊大学香槟分校联合研发 论文提出了交叉网络 (CCNet)&#xff0c;对于每个像素&#xff0c;CCNet 中的一个新的交叉注意力模块收集其交叉路径上所有像…

智慧路口:未来都市的智能节点

摘要交通路口是部署未来智慧城市的计算、通信和情报服务的最合适地点。需要收集和处理的大量数据&#xff0c;再加上隐私和安全问题&#xff0c;促使边缘计算范式的使用&#xff0c;这种范式与大都市的物理交叉路口很好地吻合。本文主要针对高带宽、低时延的应用&#xff0c;在…

2007-2022年消费者信心、满意度、预期指数月度数据(CCI、CEI、CSI、CGPI)

根据企业商品价格指数与消费者信心指数、消费者满意指数、消费者预期指数的月度数据&#xff0c;可以探究商品价格对消费者信心的影响作用和作用机制。 商品价格与消费者信心的三类细分指数均具有滞后二阶关联&#xff0c;其中&#xff0c;商品价格对对消费者预期指数的影响作…

IndexedDB的包装器JsStore - 实现登录功能及事务处理

JsStore是IndexedDB的包装器。它提供了简单的SQL像api&#xff0c;这是容易学习和使用。 IndexedDb查询可以在web worker内部执行&#xff0c;JsStore通过提供一个单独的worker文件来保持这种功能。 最近有位叫Pioneer网友一直在问我关于事务的实现方式&#xff0c;关于…

谷粒学院——Day13【微信扫描登录】

OAuth2 OAuth2的使用场景 一、OAuth2解决什么问题 1. OAuth2提出的背景 照片拥有者想要在云冲印服务上打印照片&#xff0c;云冲印服务需要访问云存储服务上的资源。 2. 图例 资源拥有者&#xff1a;照片拥有者。 客户应用&#xff1a;云冲印。 受保护的资源&#xff…

Python pandas库|任凭弱水三千,我只取一瓢饮(2)

上一篇链接&#xff1a; Python pandas库&#xff5c;任凭弱水三千&#xff0c;我只取一瓢饮&#xff08;2&#xff09;_Hann Yang的博客-CSDN博客 I~Q&#xff1a; Function10~25 Types[Function][9:25] [infer_freq, interval_range, isna, isnull, json_normalize, lres…

④【Maven】Maven的构建命令

个人简介&#xff1a;Java领域新星创作者&#xff1b;阿里云技术博主、星级博主、专家博主&#xff1b;正在Java学习的路上摸爬滚打&#xff0c;记录学习的过程~ 个人主页&#xff1a;.29.的博客 学习社区&#xff1a;进去逛一逛~ Maven的构建命令一、注意二、&#x1f680;清理…

指针与数组的联系与区别【一万六千字超详解】

&#x1f3d6;️作者&#xff1a;malloc不出对象 ⛺专栏&#xff1a;《初识C语言》 &#x1f466;个人简介&#xff1a;一名双非本科院校大二在读的科班编程菜鸟&#xff0c;努力编程只为赶上各位大佬的步伐&#x1f648;&#x1f648; 目录前言数组的性质1.1 数组的内存布局1…

第四章 Spring的基础用法

文章目录 Spring的起源和背景理解依赖注入Spring容器理解Spring容器中的Bean管理容器中的Bean及其依赖注入自动装配使用Java类进行配置管理使用静态工厂、实例工厂创建Bean实例抽象Bean与子Bean容器中的工厂Bean管理Bean的生命周期几种特殊的依赖注入Spring的简化配置SpEL的功…

kali中间人攻击

数据来源 一、中间人攻击原理 1. 利用的ARP协议的漏洞 2. ARP协议原理&#xff1a; 1&#xff09;发送ARP广播请求目标MAC地址 2&#xff09;目标主机发送ARP单播应答&#xff0c;响应MAC地址 3. ARP攻击原理 攻击人通过发送虚假的ARP应答实现ARP缓存投毒!而受害人没有办法进行…

文件存储案例

1.文件存储-File文件存储案例 1.1.案例要求 1.2参考代码 文件读取 百度安全验证 文件最终的保存的目录在/data/data/user/0/包/files下&#xff08;1&#xff09;布局文件 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android&q…

kubernetes中使用Service反向代理外部服务

当我们的某个服务在外部集群的时候&#xff0c;但是又想k8s集群内的应用连接它&#xff0c;这是可以创建一个service&#xff0c;用service代理外部服务&#xff0c;然后集群内就能连接该service&#xff0c;从而间接的访问外部服务。 创建一个service代理外部的服务 创建一个…

代码挑战画 魔法圣诞树

一、前言 本文会基于C# GDI技术 从零到一 实现一颗 魔法圣诞树&#xff01;源码和素材在文末全部都有&#xff01; 二、魔法圣诞树 对于用代码画圣诞树&#xff0c;网上各种编程语言像python、css、java、c/c我们都有见到过了&#xff0c;那么在绘图方面&#xff0c;还有一位…

FastDDS(6)核心库综述

Fast DDS(前身为Fast RTPS)是DDS规范的高效高性能实现,DDS规范是一种用于分布式应用软件的以数据为中心的通信中间件(DCPS)。本次回顾Fast DDS的体系结构、操作和关键特性。 架构 Fast DDS的架构如下图所示,其中可以看到具有以下不同环境的层模型。 Application layer应…

人员工装未穿戴识别检测 opencv

人员工装未穿戴识别检测基于OpenCvyolo计算机视觉深度学习技术对现场画面中人员行为着装穿戴实时监测识别&#xff0c;发现不按要求着装违规行为立即抓拍存档同步后台。OpenCV-Python使用Numpy&#xff0c;这是一个高度优化的数据库操作库&#xff0c;具有MATLAB风格的语法。所…

RabbitMQ 第一天 基础 1 MQ的基本概念 1.4 MQ 的劣势 1.5 常见的MQ 产品

RabbitMQ 【黑马程序员RabbitMQ全套教程&#xff0c;rabbitmq消息中间件到实战】 文章目录RabbitMQ第一天 基础1 MQ的基本概念1.4 MQ 的劣势1.4.1 MQ 的劣势1.4.2 小结1.5 常见的MQ 产品第一天 基础 1 MQ的基本概念 1.4 MQ 的劣势 1.4.1 MQ 的劣势 从远程调用 到 利用 MQ 作…

css实现九宫格

首先是实现九宫格的样式&#xff0c;对每一行进行偏移&#xff0c;当鼠标放上去会使他们形成一张图片。 html <div class"img_container"><div class"img1"></div><div class"img1"></div><div class"i…

2022年,来者犹可追

始料未及的是&#xff0c; 疫情持续到了2022年。好在“大疫不过三年”&#xff0c;只不过是结束来的同样措不及防&#xff0c;全家的一次高烧免疫&#xff0c;没有朋友圈中的云淡风轻&#xff0c;冷暖自知&#xff0c;希望明年能够拥有平安喜乐的时光。回首这一年&#xff0c;“…