一、JavaScript基础
变量和类型
- 1.
JavaScript
规定了几种语言类型
JavaScript中的每一个值都有他自己的类型,JavaScript规定了七种语言类型:
1.Undefined
未定义
2.Null
空,只有一个值,就是null表示空值
3.Boolean
true&false
4.String
字符串
5.Number
数字
6.Symbol
独一无二的值(ES6新定义)
7.Object
对象
- 2.
JavaScript
对象的底层数据结构是什么
es5自带的:array、object
es6自带的:set map、weakset weakmap(强引用、弱引用,Set和Map 数据结构)
简单的说,object 就是哈希表,array 是在 object 的基础上继续封装而实现的,至于 map 和 set,则是在 array 的基础上又继续封装而实现的。至于线程安全,这个是说不准的,即使 js 没有多线程,协程和异步都会导致线程不安全。
- 3.
Symbol
在实际开发中的应用、可手动实现一个简单的Symbol
1.使用Symbol来作为对象属性名(key)
- 使用Symbol来代替常量
- 使用Symbol定义类的私有属性/方法
具体可参考:https://www.jianshu.com/p/f40a77bbd74e
const name = Symbol()
const age = Symbol()
let obj ={
[name]:"一堆代码"
}
obj[age] = 28
obj[name] //'一堆代码'
obj[age] // 28
- 4.
JavaScript
中的变量在内存中的具体存储形式
JavaScript中的变量分别为基本类型和引用类型
基本类型:保存在栈内存中的简单数据段、值都是有固定大小、保存在栈空间,通过按值访问
引用类型:保存在堆内存中的对象,值大小不固定,栈内存中存放的该对象的访问地址指向堆内存中的对象,JavaScript不允许直接访问堆内存中的 位置,因此操作对象时,实际操作对象的引用
结合代码与图解
let a1 = 0; //栈内存
let a2 ="this is string" //栈内存
let b ={x:10} //变量b存在于栈中,{x:10}作为对象存在于堆中
let c =[1,2,3] //变量c存在于栈中,[1,2,3]作为对象存在于堆中
当我们要访问堆内存中的引用数据类型时
1.从栈中获取该对象的地址引用
2.再从堆内存中取得我们需要的数据
基本类型发生赋值行为
let a = 20;
let b = a;
b =30;
console.log(b,a) //30 20
image.png
在栈内存中的数据中发生赋值行为时,系统会自动为新的变量分配一个新值,最后这些变量都是相互独立互不影响的
引用类型发生赋值行为
let a = { x: 10, y: 20 }
let b = a;
b.x = 5;
console.log(a.x); // 5
image.png1.引用类型的赋值,同样为新的变量b分配一个新的值,保存在栈内存中,不同的是,这个值仅仅是引用类型的一个指针
2.他们指向同一个值,也就是地址指针相同,在堆内存中访问到的具体对象实际上是同一个
3.因为b.x发生改变,a.x也发生改变 这就是引用类型的特性
- 5.基本类型对应的内置对象,以及他们之间的装箱拆箱操作
1.装箱:
把基础数据类型转换为对应的引用类型的操作称为装箱。
var s1 = "some text"
var s2 = "s1.substring(2)"
如上,变量s1是一个基本类型值,它不是对象,所以不应该有方法。但js内部为我们完成了一系列处理(即装箱)使他能够调用方法,实现机制如下:
1.创建String类型的一个实例
2.在实例上调用指定的方法
3.销毁这个实例
var s1 = new String("some text");
var s2 = s1.substring(2);
s1 = null
console.log(s2) // me text
2.拆箱:
把引用类型转换为基础类型称为拆箱。
通过引用类型的valueOf()或者toString()方法来实现。
var objNum = new Number(123);
var objStr =new String("123");
console.log( typeof objNum ); //object
console.log( typeof objStr ); //object
console.log( typeof objNum.valueOf() ); //number
console.log( typeof objStr.valueOf() ); //string
console.log( typeof objNum.toString() ); // string
console.log( typeof objStr.toString() ); // string
- 7.null和undefined的区别
console.log(null==undefined); //true 因为两者都默认转换成了false
console.log(typeof undefined); //"undefined"
console.log(typeof null); //"object"
console.log(null===undefined); //false "==="表示绝对相等,null和undefined类型是不一样的,所以输出“false”
null
表示没有对象,即此处不应该有值
1.作为函数的参数,表示该函数的参数不是对象
2.作为对象原型链的终点
undefined
表示缺少值,即此处应该值,但没有定义
1.定义了型参,没有实参,显示undefined
2.对象属性名不存在时,显示undefined
3.函数没有写返回值,即没有写return,拿到的是undefined
4.写了return,当没有赋值 拿到的是undefined
null
默认转成0
undefined
默认转成 NaN
- 8.至少可以说出三种判断JavaScript数据类型的方式,以及他们的优缺点,如何准确的判断数组类型
1.
image.pngtypeof
typeof返回一个表示数据类型的字符串,返回结果包括:number
boolean
string
object
undefined
function
等
typeof可以对js基础数据类型做出准确的判断,在对于引用类型返回的基本上都是object。判断是引用类型,typeof使用起来比较不方便。
2.instanceof
instanceof 是用来判断是否为B的实例,表达式为:A instanceof B,如果A是B的实例,则返回true,反之,返回false*isntanceof 检测的是原型
3.Object.prototype.toString
toString是Object原型对象上的一个方法,该方法默认返回其调用者的具体类型,严格讲,是toString运行时this指向的对象类型,返回的类型格式为[object,xxx],xxx是具体的数据类型,其中包括:String,Number,Boolean,Undefined,Null,Function,Date,Array,RegExp,Error,HTMLDocument,… 基本上所有对象的类型都可以通过这个方法获取到。
4.constructor
查看对象对应的构造函数
constructor在对应对象的原型下面,是自动生成的,当我们写了一个构造函数的时候,程序会自动添加,构造函数名为:prototype.comstructor = 构造函数名
优缺点
- 9.可能发生隐式类型转换的场景以及转换原则,应如何避免或巧妙应用
可能发生隐式类型转换的场景以及转换原则:
值 | 转数字 | 转字符串 | 转布尔值 |
---|---|---|---|
undefined | NaN | “undefined” | false |
null | 0 | “null” | false |
true | 1 | “true” | |
false | 0 | “false” | |
0 | “0” | false | |
-0 | "0" | false | |
NaN | “NaN” | false | |
Infinity | “Infinity” | true | |
-Infinity | “-Infinity” | true | |
1(非零) | “1” | true | |
{}(任意对象) | 见下文 | 见下文 | true |
9 | 9 | “9” | true |
”a” | NaN | 使用.join()方法 | true |
function(){}(任意函数) | NaN | 见下文 | true |
1.运算符的转换:-,*,/,%,会将操作数转为数字去计算,但+不一样,两边纯数字会按数字相加,纯字符串会拼接,但数字与字符串也会拼接。
console.log(1 - '2'); //-1
console.log(1 * '2'); //2
2.双等号的隐式转换:
1).双等号两边只要有一边是NaN 便会返回false 且自身不相等
console.log(NaN == 1); //false
console.log(NaN == NaN);//false
console.log(undefined == NaN);//false
2).布尔值会转换为数字,false转换为0,true转换为1
console.log(0 == false); //true
console.log(1 == true); // true
3).对象转换
var a = [];
var b = [];
var c = {};
var d = {};
console.log("[] == []");
console.log(a == b); // false
console.log(a == c); // false
console.log(d == c); // false
console.log(a == !b); // true
解析:
对于前三个的原理是一样的,当两个值都是对象 (引用值) 时, 比较的是两个引用值在内存中是否是同一个对象. 因为此 [] 非彼 [], 虽然同为空数组, 确是两个互不相关的空数组, 所以为false。
而最后一个是因为右边空数组会转化为true,取反变为false,false变为0;左边空数组变为空字符串再变为0,0==0就为true。
如何避免或巧妙应用
把字符串类型转换为数字
image.png
- 10.出现小数精度丢失的原因,JavaScript可以存储的最大数字、最大安全数字,JavaScript处理大数字的方法、避免精度丢失的方法
出现小数精度丢失的原因
0.1 + 0.2 != 0.3 // true
计算机的二进制实现和位数限制有些数无法有限表示。此时只能模仿十进制进行四舍五入了,但是二进制只有 0 和 1 两个,于是变为 0 舍 1 入。这即是计算机中部分浮点数运算时出现误差,丢失精度的根本原因。
JavaScript可以存储的最大数字、最大安全数字
js的number类型有最大值(安全值)。即2的53次方,为9007199254740992。如果超过这个值,那么js会出现不精确的问题。这个值为16位。
JavaScript处理大数字的方法、避免精度丢失的方法
对于整数,前端出现问题的几率可能比较低,毕竟很少有业务需要需要用到超大整数,只要运算结果不超过 Math.pow(2, 53) 就不会丢失精度。
对于小数,前端出现问题的几率还是很多的,尤其在一些电商网站涉及到金额等数据。解决方式:把小数放大倍数(乘倍数),再缩小回原来倍数(除倍数)
网友评论