属性值是变量时獲取json值為undefined_一名【合格】前端工程师的自检清单-变量和类型...

17a8766c5e864f600fabb97d2e72d412.png

1.JavaScript规定了几种语言类型

七大类型:Number、Boolean、String、undefined、null、Symbol、Object

详细说一下null与undefined

  1. null是JavaScript语言的关键字,而undefined是JavaScript预定义的全局变量,不是关键字。并且,在ECMAScript 3中,undefined是可读、可写的变量,可以给它赋任何值,这个错误在ECMAScript 5中做了修正,在该版本中undefined是只读的
  2. 执行typeof运算,null返回“object”字符串,undefined返回“undefined”字符串;
  3. undefined在根据需要自行转换为字符串是转换为"undefined",而null转换为"null";
  4. undefined在根据需要自行转换为数字时转换为NaN,而null转换为0。
  5. 至于把null和undefined做比较,null == undefined 返回true,null === undefined 返回false。可以认为undefined是表示系统级的、出乎意料的或类似错误的值的空缺,而null是表示程序级的、正常的或在意料之中的值的空缺。如果想把它们赋值给变量或属性或者当做参数传入函数,最好选择使用null。

2.JavaScript对象的底层数据结构是什么

js基本类型数据都是直接按值存储在栈中的(Undefined、Null、不是new出来的布尔、数字和字符串),每种类型的数据占用的内存空间的大小是确定的,并由系统自动分配和自动释放。这样带来的好处就是,内存可以及时得到回收,相对于堆来说 ,更加容易管理内存空间。

js引用类型数据被存储于堆中 (如对象、数组、函数等,它们是通过拷贝和new出来的)。其实,说存储于堆中,也不太准确,因为,引用类型的数据的地址指针是存储于栈中的,当我们想要访问引用类型的值的时候,需要先从栈中获得对象的地址指针,然后,在通过地址指针找到堆中的所需要的数据。

堆&栈

两者都是存放临时数据的地方。

栈是先进后出的,就像一个桶,后进去的先出来,它下面本来有的东西要等其他出来之后才能出来。

堆是在程序运行时,而不是在程序编译时,申请某个大小的内存空间。即动态分配内存,对其访问和对一般内存的访问没有区别。对于堆,我们可以随心所欲的进行增加变量和删除变量,不用遵循次序。

栈区(stack) 由编译器自动分配释放 ,存放函数的参数值,局部变量的值等。

堆区(heap) 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。

堆(数据结构):堆可以被看成是一棵树,如:堆排序;

栈(数据结构):一种先进后出的数据结构。

JS Object原理

10f3ec6f6d0d58a547614f3a6e14b638.png

e52faeecf3417b271e475287fc360c50.png
//FixedArray即Descriptor
../../v8/src/runtime/http://runtime-literals.cc 72 constant_properties:
0xdf9ed2aed19: [FixedArray]
– length: 6
[0]: 0x1b5ec69833d1 <String[4]: name>
[1]: 0xdf9ed2aec51 <String[3]: yin>
[2]: 0xdf9ed2aec71 <String[3]: age>
[3]: 18
[4]: 0xdf9ed2aec91 <String[8]: -school->
[5]: 0xdf9ed2aecb1 <String[11]: high school>
//此map对应HiddenClass
../../v8/src/heap/http://heap.cc 3472 map is
0x21528af9cb39: [Map]
– type: JS_OBJECT_TYPE
– instance size: 48
– inobject properties: 3
– back pointer: 0x3e2ca8902311 <undefined>
– instance descriptors (own) #0: 0x3e2ca8902231 <FixedArray[0]>

相关链接:Js底层对象原理 从Chrome源码看JS Object的实现

3.Symbol类型在实际开发中的应用、可手动实现一个简单的Symbol

应用:由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。这对于一个对象由多个模块构成的情况非常有用,能防止某一个键被不小心改写或覆盖

要动手实现简单的Symbol需要了解当调用 Symbol 的时候,会采用以下步骤:

  1. 如果使用 new ,就报错
  2. 如果 description 是 undefined,让 descString 为 undefined
  3. 否则 让 descString 为 ToString(description)
  4. 如果报错,就返回
  5. 返回一个新的唯一的 Symbol 值,它的内部属性 [[Description]] 值为 descString

(function() { var root = this; var SymbolPolyfill = function Symbol(description) { // 实现特性第 2 点:Symbol 函数前不能使用 new 命令 if (this instanceof SymbolPolyfill) throw new TypeError('Symbol is not a constructor'); // 实现特性第 5 点:如果 Symbol 的参数是一个对象,就会调用该对象的 toString 方法,将其转为字符串,然后才生成一个 Symbol 值。 var descString = description === undefined ? undefined : String(description) var symbol = Object.create(null) Object.defineProperties(symbol, { '__Description__': { value: descString, writable: false, enumerable: false, configurable: false } }); // 实现特性第 6 点,因为调用该方法,返回的是一个新对象,两个对象之间,只要引用不同,就不会相同 return symbol; } root.SymbolPolyfill = SymbolPolyfill;

详细模拟查看模拟实现 Symbol 类型

4.JavaScript中的变量在内存中的具体存储形式

js基本类型数据都是直接按值存储在栈中以直接量的形式存储

js引用类型数据被存储于堆中,而引用类型数据的具体引用则在栈中存储


5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作

基本数据类型:Undefined Null Boolean Number String

内置对象:Object是Javascript中所有对象的父对象

数据封装对象:Object Array Boolean Number String

其他对象:Function Argument Math Date RegExp Error

js中的==与===的区别

一个是判断值是否相等,一个是判断值及类型是否完全相等。

要注意相等(==)和全等(===)的区别!全等不会出现类型转换

下面的规则用于判定===运算符比较的两个值是否相等的判断条件

•如果两个值的类型不同,它们就不相同。

•如果两个值是数字,而且值相同,那么除非其中一个或两个都是NaN(这种情况它们不是等同的),否则它们是等同的。值NaN永远不会与其他任何值等同,包括它自身(奇怪的家伙),要检测一个值是否是NaN,可以使用全局函数isNaN()。

•如果两个值都是字符串,而且在串中同一位置上的字符完全相同,那么它们就完全等同。如果字符串的长度或内容不同,它们就不是等同的。

•如果两个值都是布尔型true,或者两个值都是布尔型false,那么它们等同。

•如果两个值引用的是同一个对象、数组或函数,那么它们完全等同。如果它们引用的是不同的对象(数组或函数),它们就不完全等同,即使这两个对象具有完全相同的属性,或两个数组具有完全相同的元素。

•如果两个值都是null或都是undefined,它们完全相同。

6.理解值类型和引用类型

js基本类型数据都是直接按值存储在栈中以直接量的形式存储

js引用类型数据被存储于堆中,而引用类型数据的具体引用则在栈中存储

值类型和引用类型的区别

7.nullundefined的区别

同1

8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型

JavaScript数据类型的方式

  • typeof 用来判断基本类型,typeof用于引用类型值都为"object"。
  • instanceof 用来判断引用类型
  • constructor
  • Object.prototype.isPrototypeOf
  • Object.prototype.toString

准确的判断数组类型


1.基于 instanceof

a instanceof Array; // true

2. 基于 constructor

a.constructor === Array;// true

3. 基于 Object.prototype.isPrototypeOf

Array.prototype.isPrototypeOf(a);

4. 基于 Object.prototype.toString `

Object.prototype.toString.apply(a) === '[object Array]';

通常方法④被认为是最稳妥的方法,这也是一些框架用于判断数组类型使用的方法。前三种方法的准确性很容易遭到篡改:

var a = { __proto__: Array.prototype };

以上,前三种方法都返回true,这种不负责任的继承方式使得基于继承的判断方案失效。

9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用

字符串转换

String方法是toString在功能上的超集,String相比toString增加了对null和undefined的支持。

数值转换

转为数值的情况与转为字符串类似,不过对应的两个方法是对象的valueOf和Number构造函数。请注意,NaN也是一个数值

  • 6大数据类型,除了null和undefined,都可以直接调用其valueOf方法来尝试转为其本身所代表的原始数据类型,但是相当一部分时候是不会转为数值的,尤其是对象。

Number构造方法,一定会把传入的值转化为数值。Number构造函数对于传入参数的具体操作是:

  • 字符串,忽略前导0,转为数值。转换不成功(出现任何不符合数字形式的字符)则为NaN
  • 若参数是对象,先调用其valueOf方法,如果返回的不是一个数值,那么调用其toString方法,再将这个字符串作为Number的参数传入,得出最终结果。
  • undefined转为NaN,null转为0
  • true转为1,false转为0

布尔转换

  • 对于数值,NaN和0转为false
  • 对于字符串,空字符串转为false
  • null和undefined都转为false
  • Symbol(ES6)和对象(不算null)全转为true

Symbol只能转布尔值和字符串,转其他类型全报错。

10.出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法

IEEE754 规定,对于 32 位的单精度浮点数,最高的 1 位是符号位 S,接着的 8 位是指数 E,剩下的 23 位为有效数字 M。

对于 64 位的双精度浮点数,最高的 1 位是符号位 S,接着的 11 位是指数 E,剩下的 52 位为有效数字 M。

位数阶数有效数字 / 尾数单精度浮点数32823双精度浮点数641152

大整数的精度丢失和浮点数本质上是一样的,尾数位最大是 52 位,因此 JS 中能精准表示的最大整数是 Math.pow(2, 53),十进制即 9007199254740992(Number.MAX_SAFE_INTEGER+1)

大于 9007199254740992 的可能会丢失精度

JavaScript可以存储的最大数字:Number.MAX_VALUE

9007199254740992 >> 10000000000000...000 // 共计 53 个 0 9007199254740992 + 1 >> 10000000000000...001 // 中间 52 个 0 9007199254740992 + 2 >> 10000000000000...010 // 中间 51 个 0

实际上

9007199254740992 + 1 // 丢失 9007199254740992 + 2 // 未丢失 9007199254740992 + 3 // 丢失 9007199254740992 + 4 // 未丢失

结果如图

f860f4d3fff1ac022f0426cf7e4b3837.png

以上,可以知道看似有穷的数字, 在计算机的二进制表示里却是无穷的,由于存储位数限制因此存在“舍去”,精度丢失就发生了。

处理方法

对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。

对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放到位整数(乘倍数),再缩小回原来倍数(除倍数)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值