JS基础知识盲点

查缺补漏 - JS基础知识补充。 -《重学前端》

类型

七种数据类型:String、Number、Null、Undefined、Boolean、Object、Symbol。

  1. Number浮点数的运算精度无法用===来比较。
    使用Number提供的最小精度来比较Number.EPSILON

    // 示例
    0.1 + 0.4 === 0.5     // true
    0.1 + 0.7 === 0.8     // false 0.1 + 0.7 = 0.799999999999
    // 使用最小精度比较
    Math.abs(0.1 + 0.7 - 0.8) <= Number.EPSILON        // true
    
  2. 类型转换,数据类型的隐式转换,推荐显示转换后===进行比较

    字符串转数值
    parseInt - 参数为要解析的值、要转换的进位数(2-36),无法转换返回NaN。
    parseFloat - 参数为需要解析转换的值,不能转换则返回NaN。
    Number - 构造函数处理转换。

    // parseInt parseFloat
    parseInt("10");      // 10
    parseInt("10",2);          // 2
    // 
    Number("10");           // 10
    

    装箱转换
    概念:将基本类型转换为对应的对象。

    Object.prototype.toString 可以识别对象对应的基本类型。

    针对于经过装箱的需要配合typeof区分基本类型还是对象类型。

    // typeof
    let fn = new Function();
    typeof fn;       // "function"
    fn.toString();           // "function anonymous(){}"
    // 
    fn = Object.prototype.toString.call(fn);
    typeof fn;         // "string"
    fn.toString();         // "[object Function]"
    

    拆箱转换

    概念:现将对象变成基本类型,再从基本类型转换为对应的其他类型。在标准中存在toPrimitive方法进行拆箱转换。

      拆箱转换会调用valueOftoString来获得基本数据类型。string会先调用toString方法,都不存在时会抛出错误TypeError

     // 1. 定义类型转换 转换为 String
    let obj = {
    	valueOf:()=>{console.log("valueof"); return Function},
    	toString:()=>{console.log("toString"); return Function}	
    }
    String(obj);          
    // toString
    // valueof
    // TypeError
    
    // 2. 转换 Number
    Number(obj);
    // valueof
    // toString
    // typeError
    
    // 3. 找到对应的类型后结束调用
    let obj = {
    	valueOf:()=>{console.log("valueof"); return Function},
    	toString:()=>{console.log("toString"); return "private"}	
    }
    String(obj);  
    // toString
    // "private"
    
    // 4. 自定义行为 ES6
    obj[Symbol.toPrimitive] = ()=>{console.log("primitive"); return "toPrimitive"}
    String(obj);
    // primitive
    // "toPrimitive"
    

对象

JS对象:核心是理解原型链prototype.

使用new运算符:

  1. 以构造器的prototype属性为原型,创建新对象;
  2. this和传递的参数传给构造器;
  3. 如果构造器返回的是对象,则返回;否则返回创建的新对象。
function User(){
	this.name = "admin";
	this.getAge = function(){
		return 25;	
	}
}
User.prototype = {
	getName:function(){
		return this.name;
	}
}
// 实例化调用
let user = new User;
user.getName();        // "admin"

new User()new User返回的是一样的。

ES6的Class语法,之前一些过文章ES6 - 类(class)、修饰器:

JS 对象分为宿主对象(即有运行时环境决定)、内置对象(包含固有对象、原生对象、普通对象);

JS 执行

  由宿主环境发起的任务为宏观任务;由JS 引擎发起的任务为微观任务。一个宏观任务包含多个微观任务,待微观任务执行完,这整个宏观任务执行结束。

Promise与setTimeout

Promise内部的执行代码比setTiemout先执行。

setTimeout属于宿主对象,属于宏观任务;Promise是js标准内置对象,属于微观任务。
代码执行顺序:

Promise
同步代码块执行
then调用 执行
同步代码执行
setTimeout执行

代码分析:

	// 1. 加入一个宏观任务,待执行
   	setTimeout(()=>console.log("d"), 0)
   	// 2. promise 执行,内部代码会同步执行 输出 "a"
    var r = new Promise(function(resolve, reject){
    	console.log("a");
        resolve()
    });
    // 3. then 调用 执行输出 c1 
    r.then(() => { 
        console.log("c1") ;
        // 3-1 promise 微任务执行,直接调用输出 c2 
        new Promise(function(resolve, reject){
            resolve()
        }).then(() => console.log("c2"))
    });
    // 微任务执行完成之后,执行宏任务, 输出 d 

结果输出:
JS基础知识盲点_第1张图片

JS 执行

void运算会忽略表达式的值,返回的undefined。

JS 立即执行函数:

(function(){
	console.log("a");
})()

// 使用void 
void function(){
	console.log("a");
}()

语法

JS 执行有两个阶段:预处理(处理声明的变量)、执行阶段

最为难理解的就是var声明的变量的取值。

示例分析:

  1. 预处理阶段 - 全局作用域内声明a;声明了foo函数,且在内声明覆盖了a
  2. 执行阶段 - 全局作用域赋值 a=1 打印输出 1
  3. 执行foo() - 预处理阶段已重新声明了a但未赋值。打印输出undefined
  4. 执行赋值a=2 - 打印输出 2.
  5. 最后输出全局变量a 打印1
var a = 1;
function foo() {
    console.log(a);
    var a = 2;
    console.log(a);
}
console.log(a);
foo();
console.log(a);

function 在普通声明方法时,在预处理阶段会赋值;非正常声明时,只有声明;
示例分析:

  1. 函数的正常声明,打印结果为 fn;
  2. 带有条件语句的声明是,打印结果为undefined;
// 1. 输出 fn
console.log(fn);
function fn(){
	//...
}
// 2. 在其他语句中执行声明
console.log(fn);
if(true){
	function fn(){
		// ...
	}
}
break、continue语句

break用于跳出循环语句或switch语句;continue用于结束本次循环继续下次循环。

这里需要示例的时带标签的语法
四个示例:

  1. break跳出本次循环。上层循环继续执行;
    JS基础知识盲点_第2张图片
  2. break tag_1跳出指定的循环;
    JS基础知识盲点_第3张图片
  3. continue跳过本次循环,继续下次循环;
  4. continue tag_1跳出循环到指定的循环体中,继续下次循环。
// 1. 跳出指定循环体
tag_1:for(let i=0;i<4;i++){
	tag_2:for(let j=0;j<4;j++){
		let num = i*j;
		if(num === 4){
			break tag_1;
		}
		console.log(i,j);
	}
}
// 2. 跳出本次循环
tag_1:for(let i=0;i<4;i++){
	tag_2:for(let j=0;j<4;j++){
		let num = i*j;
		if(num === 4){
			break;
		}
		console.log(i,j);
	}
}
表达式

说明:

  1. ** 乘方表达式;
  2. 移位表达式:>>左移、<<右移、>>>无符号右移。
    1. 左移n位相当于乘以2的n次方。
    2. 右移n位相当于除以2,取整n次。
    3. 无符号右移会把减号视为符号位,参与移位。
  3. 位运算:&与运算、|或运算、^异或运算符。
    1. 异或运算表达:相同时为 0 ,不同时为1
// 1. 乘方表达式
2**10          // 1024
(-2) ** 10       // 1024
// 2. 移位表达式
2>>3           // 10 右移三位 为 0 
2<<3         // 10 左移三位 10000 为 16	

// 3. 位运算
3&5           // 011 & 101 结果 001  1
3|5           // 结果 111 7
3^5           // 结果 110 6

你可能感兴趣的:(JavaScript,JS,对象,JS知识补充)