javascript复习1,14个知识点,有需任取

1.延迟加载js的方法:defer和async

<script defer type="text/javascript" src="script.js"></script>
    defer:等html全部解析完成,才会执行js代码,顺次执行js脚本
    async:async是和html解析同步的,不是顺次执行js脚本(谁先加载谁先执行)
demo:
    <div id="box"></div>
    <script type="text/javascript" src="script.js"></script> 
    这种写法使得先解析Dom元素,再解析js文件,这样即使我的js文件出错了,也不影响DOM元素的在页面的渲染

    <script type="text/javascript" src="script.js"></script>
    <div id="box"></div>
    将获取不到dom元素,从上往下执行


2.js数据类型

 基本:(string number boolean undifined) null symbol bigint
 引用:object
注意:NAN是一个数值类型(属于number),但是不是一个具体的数字,就像无穷那个
demo:
    alert(true + 1); //2
    alert('name' + true);//nametrue
    alert(undefined + 1)//NAN
    alert(typeof(NAN))//number
    alert(typeof(undifined))//undefined

3.null和undifined的区别

answer:先是产生了null,但null会被因式转换为0,不容易被发现错误,undifined就产生了
原先:null表示一个"无"的对象,隐式转换为数值为0,undifined是一个基本数据类型,转换为数值时是NAN
console.log(typeof null);//object
console.log(number(null));//0

4.== 和 === 

== : 比较值,另外stirng == || boolean或者number...都会隐式转换,通过valueOd转换不会显示出来,要在后台来看
 === :比较值和类型

console.log(1 == '1');
console.log(true == 1);
console.log(null == undefined);
console.log([1,2] == '1,2');

证明是valueOf转换
var s = '2';
if(s == 2){
    console.log(typeof s);//string
}
<!-- valueOf -->
Object.prototype.valueOf = fucntion(){
    alert('123';)
}
var arr = [1,2];
var str = '1,2';
console.log(arr == str)//重写方法之后返回false,valueOf不在生效


 5.Js微任务和宏任务

1.js是单线程的语言
 2.js代码执行流程是:等同步执行完再事件循环
 3.事件循环中包括微任务和宏任务(只有等同步中的任务都执行完了,才会执行事件循环的内容
 进入事件循环:请求 定时器 事件)
 微任务:promise.then
 宏任务:setTimeout...
 执行宏任务的前提是清空了所有的微任务
 流程:同步执行完 -> 事件循环中(包括微任务和宏任务) -> 微任务 -> 宏任务 -> 微任务
demo:单线程:同一时间你只能做一件事 ——>javascript 防止线程冲突 比如一个线程在某个DOM
节点上添加内容,另一个线程要删除这个节点,这是浏览器以哪个为准呢?

var box = document.getElementById('box');
box.onclick = function(){
    alert(1);
}
console.log(2);//同步
//点击任务没有执行(表示前一个线程没有干),为什么后面那个依旧可以执行呢?
//因为js尽管单线程,但是处理这样的情况,它有异步执行机制(事件循环的机制)
进入事件循环:ajax请求 定时器 事件
for(var i = 0;i < 3;i++)
    setTimeout(function(){
        alert(i)     -》3
        },1000乘以i) 
1.setTimeout一定进入事件循环当中,而for循环它是一个同步的,

 6.Js作用域
 

。除了函数外,js没有块级作用域
 。注意作用域链,内部变量访问原则...
 。注意声明变量是用var还是没有写
 。js有变量声明提升机制
 。优先级:声明变量 > 声明普通函数 > 参数 > 变量提升
 function fn(){
     var a = 10;
 }
 fn();
 console.log(a);//a is not defined 函数有scope 函数是一个obj
 var obj = {
     a:1
 }
 console.log(a)//不可以,undefined
 console.log(obj.a);//可以

 for(var i = 0;i < 10;i++){

 }
console.log(i);//因为i是在for的()里面定义的,确实没有作用域,所以可以打印出来
if

if(true){
    var a = 10;
}
console.log(1);//可以

function fun(){
    var a = 10;
}
fun();
console.log(a);//不能

但是可以这样:
function fun(){
    var a = 10;
    fucntion foo(){
        console.log(a);
    }
    foo();
}
fun();//foo拿到fun的AO和GO,当然先找内部的AO和GO

(function(){
    var a = b = 10;
})();
console.log(a);//未被定义
console.log(b);//ok b归全局所管

fucntion c(){
    var b = 1;
    function a(){
        console.log(b);//报undefined
        var b =2;
        console.log(b);//2
    }
    a();
    console.log(b);//1
}//考到了变量声明提升和函数的有作用域链的关系,先找内部AO中的变量

var name = 'a';
(function(){
    //看不见的 var name;
    if(typeof name = 'undefined'){
        var name = 'b';
        console.log('111' + name);///111b
    }else{
        console.log('222' + name);
    }
})();

console.log(a);//undefined
if(false){
    var a = 10;//函数有自己的作用域
}
console.log(a);//undefined

var bar = 1;
function test(){
    console.log(bar);//undefined
    var bar = 2;
    console.log(bar);//2
}

function fun(a){
    console.log(a);//function a(){} 如果没有参数a,那就是Undefined
    var a = 10;
}
fun(100);

function fun(a){
    var a = 10;
    function a(){};
    console.log(a);//10
}
fun();

优先级¥¥
function fun(){
    var a = 10;
    function (){};
    console.log(a);//不会打印函数体,因为优先级中变量声明 > 函数声明
    这样子 var a = function(){};//才会打印函数体
}

 7.Js对象

。对象都是new操作符构建出来的,所以两个长得一样对象之间不相等(引用除外)
。它是应用类型(共同的一个地址)
。对象的key都是字符串类型
。对象找属性/方法原则
 先在对象本身找 -> 构造函数找 ->对象原型找 -> 构造函数原型找 -> 对象上一层原型查找
demo:一切事物皆对象
console.log([1,2,3] === [1,2,3])//false 两个不同的"人"

new 创建一个新对象
var obj1 = {
    a:1
}
var obj2 = obj1;//拿到了引用
obj2.a = '111'
console.obj2.a;//地址改变

var arr1 = [1,2,3];
var ar2 = arr1;
console.log(arr1 === arr2)//用一个地址

var obj1 = {
    a:'hello'
}
var obj2 = obj1;
obj2.a = 'world';
console.log(obj1);//{a:world}
(funcition(){
    console.log(a);//undefined
    var a = 1;
})();

var obj = {
    b:'2'
}
var obj1 = {
    a:"1"
}
obj1[obj] = '123'
for (var k in obj1){
    console.log(k)//a
    console.log(typeof k)//string obj1[obj] = '123'变[Object object](它是一个string数据类型)
}
console.log(obj1)

var a = {};//相当于{[object Object]:123}再后者覆盖前者{[object Object]:456} C从对象变成string
var b = {
    key:'a'
}
var c = {
    key:'c'
}
a[b] = '123';
a[c] = '456';
console.log(a[b])//456
// 例如 var m = {};m.a = 1;m.a = 2;那么最终后者会覆盖前者

每一个对象都是通过构造函数构造出来的
function Array(){}//为其构造函数
console.log([12,3,3].constructor);
function Fun(){}//构造函数
let obj = new Fun();
console.log(obj.constructor)

每一个函数都自带一个prototype(原型),new Fun 该Fun构造函数的原型指向于对象(new Fun)的原型
// Fun.prototype == obj.__proto__

// 对象查找属性方法的原型链规则
function Fun(){
    this.a = '在Fun函数中添加的'
}
Fun.prototype.a = '这是Fun原型添加的'
let obj = new Fun();
obj.a = '对象本身'
obj.__proto__.a = '这是对象原型添加的'
Object.prototype.a = '这是Object添加的'
// console.log(obj.__proto__.__proto__.__proto__ )

 8.Js的this指向和原型

demo:
 function fun(){
    // this.a = '123'
    console.log(this)
    console.log(1)
    return 'a'
}
//console.log(fun) fun  -> 在控制台的话打印函数体
// fun(); -> 2
//console.log(fun()); -> 1 a
//console.log(new fun()) ->返回一个对象 和 1
console.log(new fun())//this不再是指向window了
console.log(fun ())//相当于全局的,window.fun();返回window对象

function Foo(){
    getName = function(){console.log(1)}  //getName属于window,因为不是this.getName......
    return this;
}
Foo.getName = function(){console.log(2)}//函数本身添加
Foo.prototype.getName = function(){console.log(3)}//函数原型添加
var getName = function(){console.log(4)}//普通变量
function getName(){    //函数声明
    console.log(5)
}
Foo.getName();//2
getName();//4 Foo()未执行 而是Foo.getName 而不是Foo().getName,(如果是就是1,window.getName(),那么1就会覆盖了4) 只能从下面的变量声明和函数声明中选择了,所以根据作用域
Foo().getName;//1
Foo.getName();//1
getName();//1
new Foo().getName();//3   记住查找顺序

var obj = {
    a:10,
    b:{
        fn:function(){
            console.log(this.a);//b里面没有a这个key,也即是b对象没有a这个属性
            console.log(this);//打印函数体
        }
    }
}
obj.b.fn();  //b调用函数(),所以this指向了b对象

window.name = 'hello';
function A(){
    this.name = 123
}
A.prototype.getA = function(){
    console.log(this);
    return this.name + 1;
}
let a = new A();
let funcA = a.getA();//a.getA 和 a.getA()的区别主要是,因为不是后者,我们知道a.getA是返回的是函数体
funcA();//this指向window hello1 现在因为它没有执行相当于把函数体赋值给了funA,let funA = function(){console,log(this)...}
// 如果是let ... = a.getA();那么this指向了调用对象A 最后输出124

var length = 10;
function fn(){
    return this.length + 1;
}
var obj = {
    length:5,
    test1 : function (){
        return fn();
    }
    //test2:function(){return this.length + 1}//return 6,里面的this指向Obj,fn中的this指向window
}
obj.test2 = fn;//又是把函数体赋过来了obj.test2 = fn(){return...}
console.log(obj.test1());//11 里面fn()执行 其中里面的this指向了window,这个过程中产生了闭包
console.log(fn() === obj.test2());//false
console.log(obj.test1() == obj.test2());///false 11 5

 9.判断变量是不是数组
     

方法一 : Array.isArray(arr);
     方法二(不是特别严谨) : instanceof -> arr instance Array
     方法三 : 通过原型 Object.prototype.toString.call(arr).indexOf('Array') 返回不是-1就是数组 Object.prototype.toString.call(arr)已经是[object Array],是一个string
     方法四 : isPrototypeOf()    Array.prototypeisPrototypeOf(arr)
     方法五 : constructor arr.constructor.toString().indexOf('Array')  > -1

 10.slice
 

。用于截取,
     参数可以是slice(3) slice(1,3) slice(-3)
 。splice : 可以插入 删除 替换
      返回删除的元素
      该方法会改变原数组
// demo:
var arr1 = ['1','2','3','4'];
var arr2 = arr1.slice(-2)//左开右闭
var arr3 = arr1.slice(-2)
console.log(arr3)
console.log(arr2)
//slice返回一个新数组,2
var e = ['1','2','3','4','5','6'];
var t = e.splice(0,1)//从一开始的后一个元素
console.log(t)
console.log(e)

 11.数组去重

 法一:new Set
 var arr1 =[1342,1,2,3,3,1];
 fucntion unique)(arr){
     return [...new Set(arr)]//new set返回的是一个obj,可以用Array.from(new Set(arr))转化为数组, 
 }
 console.log(unique(arr));
 法二:indexOf
 var arr2 = [1342,1,2,3,3,1];
 fucntion unique(arr){
     var brr = [];
     for(var i = 0;i < arr.length; i++)
     {
         if(brr.indexOf(arr[i] == -1))
         {
             brr.push(arr[i]);
         }
     }
     return brr;
 }
 console.log(unique(arr2));
法三:sort
var arr3 = [1342,1,2,3,3,1];
function unique(arr){
    arr = arr.sort();
    var brr = [];
    for(var i = 0;i < arr.length;i++)
    {
        if(arr[i] !== arr[i -1])
        {
            brr.push(arr[i]);
        }
    }
    return brr;
}
console.log(unique(arr3));


12.多维数组中的max

a = [
    [4,5,1,3],
    [12,23,12,667],
    [87,23,56,78],
    [1000,1001,893,2]
]
输出 : [5,667,87,1001]
function fn(arr){
    var newArr = [];
    arr.forEach((item,indx) => {
        newArr.push(Math.max(...item))
    })
    return newArr;
}
console.log(fn(a));

13.字符串新增方法
  

 String.prototype.addPrefix = function(str){
        return str + this;
    }
    console.log('爱你' + addPredix('我'));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值