js零碎知识点

170 阅读7分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第1天,点击查看活动详情

  • && 优先级高于 ||

    console.log(3 || 2 && 1)  //3  
    先算2&&1,返回2,再算3||2,返回3
    
  • 读取对象值 对象名.属性===对象名[‘属性’],一般使用.即可,在遇到属性为变量时,必须用[]

    let obj = { name : 'xiaolin' }
    console.log(obj.name === obj['name'])  //true
    
  • 基本数据类型:string number boolen null undefined Symbol,引用数据类型:object

  • 基本数据类型存储在栈内存中,变量值保存值;对象存储在堆内存中,变量值保存地址,在赋值时两个变量指向同一个内存地址(引用)

  • 深浅拷贝(深浅复制),一句话总结,基本数据类型没有深浅拷贝之分,默认为深拷贝,拷贝的都是具体的值的副本;对于引用数据类型来说,浅拷贝拷贝的是对象引用的地址,深拷贝拷贝的是具体的值的副本

    //基本数据类型,在复制后修改使用彼此间不会互相影响
    let str = 'xiaolin'
    let str2 = str
    console.log(str)  //xiaolin
    console.log(str2)  //xiaolin
    
    str = 'xiaolin6'
    console.log(str)  //xiaolin6
    console.log(str2)  //xiaolin
    
    //引用数据类型-浅拷贝,拷贝了堆内存中的地址,在复制后修改使用彼此间会互相影响
    let obj = {
      name:'xiaolin',
      age:24
    }
    let obj2 = obj
    console.log(obj)  //{name:'xiaolin',age:24}
    console.log(obj2)  //{name:'xiaolin',age:24}
    
    obj.name = 'xiaolin6'
    console.log(obj)  //{name:'xiaolin6',age:24}
    console.log(obj2)  //{name:'xiaolin6',age:24}
    
    
    //引用类型-深拷贝
    //1.Object.assign
    let obj = {
      name:'xiaolin',
      age:24
    }
    let obj2 = Object.assign({},obj)
    console.log(obj);  //{name:'xiaolin',age:24}
    console.log(obj2);  //{name:'xiaolin',age:24}
    
    obj.name = 'xiaolin6'
    console.log(obj)  //{name:'xiaolin6',age:24}
    console.log(obj2)  //{name:'xiaolin',age:24}
    
    //2.递归
    var obj = { name:'xiaolin' }
    function deepCope(target) {
      let res
      if(typeof(target) === 'object'){
        if(Array.isArray(target)){
          res = []
          for(let i in target){
            res.push(deepCope(target[i]))
          }
        } else if (target === null){
          res = null
        } else if (target instanceof RegExp){
          res = RegExp
        } else {
          res = {}
          for(let i in target){
            res[i] = deepCope(target[i])
          }
        }
      } else {
        res = target
      }
      return res
    }
    var obj2 = deepCope(obj)
    console.log(obj2)  //{name:'xiaolin'}
    
    obj2.name = 'xiaolin6'
    console.log(obj)  //{name:'xiaolin'}
    console.log(obj2)  //{name:'xiaolin6'}
    
  • var变量声明提升,把声明提到最前面再依次执行;函数声明提前,可以在创建前调用 

    var a = 2; console.log(a)  //undefined
    //等同于var a; console.log(a), a = 2  //undefined
    
    foo();  //具名函数先调用后定义可以正常使用,存在函数提升,输出foo
    function foo() {
      console.log('foo');
    }
    
  • 变量的查找,函数在本级找变量,找得到用本级,找不到往上一级找,即作用域链

    function wrap() {
      var a = 1
      return function () {
        console.log(a)  //变量a在本作用域找不到值,往上一层找,以此往上直到全局
      }
    }
    wrap()()  //1
    
  • 构造函数,先定义一个构造函数,再new一个实例

    function People(name) {
      this.name = name;
      this.getName = function(){
        console.log(this.name);
      }
    }
    var p1 = new People('xiaolin')  //new一个实例
    p1.getName();  //调用,输出xiaolin
    
  • 每个构造函数都有一个属性prototype,对应一个原型对象 == 在构造函数上new的实例都有一个__proto__属性,对应一个原型对象实例找属性时首先向构造函数找再向原型找,原型对象就像是一个公共区域,可以把共有的属性和方法添加到原型对象,避免污染全局,可以通过hasOwnProperty方法检查自身有没有该属性

    function People(name,age) {
      this.name = name;
      this.age = age;
      this.getName = function(){
        console.log(this.name);
      }
    }
    var p1 = new People('xiaolin',24)
    p1.getAge()  //报错,方法未定义
    
    People.prototype.getAge = function () {  //在原型上添加
      console.log(this.age);
    }
    
    var p2 = new People('xiaolin',24)
    p2.getAge()  //24
    
    console.log( p2.hasOwnProperty('getAge'));  //false,方法存在原型上,不在构造函数上
    
    console.log(People.prototype === p2.__proto__);  //true
    
  • 在打印对象时输出[object,object]是因为输出时调用了toString()方法,如果希望在输出对象时不输出[object Object],可以为对象的原型上修改toString()方法

    var arr = [11,22,33]
    //for循环
    for(let i =0;i<arr.length;i++){
      console.log(arr[i]);  //11,22,33
    }
    //forEach
    arr.forEach((val)=>{
      console.log(val); //11,22,33
    })
    
  • 数组方法

    var arr = [11,22,33]
    var res = arr.push(44)
    console.log(res,arr)  //4,[11,22,33,44],最后面新增,返回新的长度
    
    var arr = [11,22,33]
    var res = arr.pop()
    console.log(res,arr);  //33,[11,22],删除最后一个,返回删除元素
    
    var arr = [11,22,33]
    var res = arr.unshift(44)
    console.log(res,arr);  //4,[44,11,22,33],在前面新增,返回新的长度
    
    var arr = [11,22,33]
    var res = arr.shift()
    console.log(res,arr);  //11,[22,33] ,删除最前面一个,返回删除元素
    
    var arr = [11,22,33]
    console.log(arr.slice(1,3)); //[22,33] ,截取,前开后闭
    
    var arr = [11,22,33]
    arr.splice(1,1)
    console.log(arr); //[11,33],删除,(index,num)
    
    var arr = [11,22,33]
    arr.splice(1,1,44)
    console.log(arr); //[11,44,33],替换,(index,1,newchange)
    
    var arr = [11,22,33]
    arr.splice(1,0,44)
    console.log(arr);  //[11,44,22,33],增加,(index,0,newadd)
    
    var arr = [11,22,33]
    var arr2 = [44,55]
    console.log(arr.concat(arr2));  //[11,22,33,44,55],数组连接
    
    var arr = [11,22,33]
    console.log(arr.join());  //11,22,33,数组转字符串
    
    var arr = [11,22,33]
    console.log(arr.reverse());  //[33,22,11],数组反转
    
    var arr = [11,22,33]
    console.log(arr.sort((a,b)=>{
      return a-b;  //从小到大排序
      return b-a   //从大到小排序
    }));
    
  • 数组遍历

    var arr = [11,22,33]
    //for循环
    for(let i =0;i<arr.length;i++){
      console.log(arr[i]);  //11,22,33
    }
    //forEach
    arr.forEach((val)=>{
      console.log(val); //11,22,33
    })
    
  • 数组去重,for双循环

    var arr = [33,11,22,33,44,22,22,11,55,55,66]
    for(let i = 0;i < arr.length; i++){
      for(let j = i+1;j < arr.length;j ++){
        if(arr[i] === arr[j]){
          arr.splice(j,1);
          j--;
        }
      }
    }
    console.log(arr);
    
  • call和apply,都是函数对象的方法,需要函数对象调用,传的第一个参数可以改变执行上下文的this,call第二个参数是依次传,apply第二个参数是数组

    var sing = {
      singing:function(name,skill){
        this.skill = skill
        this.name = name
        console.log(`my name is ${this.name},can ${this.skill} and ${this.skill2}`,);
      }
    }
    var dance = {
      skill2:'sleep'
    }
    sing.singing.call(dance,'xiaolin','dance')  //my name is xiaolin,can dance and sleep
    sing.singing.apply(dance,['xiaolin','dance2'])  //my name is xiaolin,can dance2 and sleep
    
  • argument是类数组,保存传递的实参

    function add() {
      console.log(Array.isArray(arguments));  //false,arguments是类数组
      let sum = 0
      for(let i=0;i<arguments.length;i++){
        sum += arguments[i]
      }
      return sum
    }
    var getSum = add(1,2,3,4,5,6,7,8,9)
    console.log(getSum);  //45
    
  • 字符串方法

    console.log('xiaolina'.charAt(5))  //i,索引所在字符
    
    console.log('xiao'.concat('lina'))  //xiaolina,拼接字符串
    
    console.log('xiaolina'.indexOf('a'))  //2,从前往后检索字符串,有则返回第一个index,
    console.log(('xiaolina'.indexOf('h')))  //-1,无返回-1
    
    console.log('xiaolin'.lastIndexOf('a')) //7,同indexOf,顺序从后往前
    console.log('xiaolin'.lastIndexOf('h'));  //-1,无返回-1
    
    console.log('xiaolin'.slice(1,3));  //ia,截取字符串,左闭右开
    
    console.log('xiaolina'.substr(2,3));  //aol,截取字符串,(index,num)
    
    console.log('xiaoxiaoxiao'.split('o'));  //[xia,xia,xia,'']
    
  • this指向

    //1.函数调用
    function foo() {
      window.x = 1
      console.log(this.x);
    }
    foo()  //通过函数调用,this永远是window
    
    //2.方法调用
    var obj = {
      name:'xiaolin',
      foo(){
        console.log(this.name);
      }
    }
    obj.foo()  //'xiaolin',通过方法调用,this指向调用方法的对象
    
    //3.构造函数调用
    function People() {
      return this
    }
    var p1 = new People()
    console.log(p1)  //People,通过new创建实例,this指向新的实例对象
    
    var p2 = People()
    console.log(p2)  //Window,函数调用this指向window
    
    4.以apply和call调用,this是第一个参数
    
  • window.onload在文档加载完成之后就会触发该事件,可以为此事件注册事件处理函数,并将要执行的脚本代码放在事件处理函数中,就可以避免获取不到对象的情况。当js代码需要获取页面中的元素时,如果script标签在元素的前面,需要加window.onload;如果script放在了元素后面,就不需要加 window.onload

  • js、json互转

    //js对象转json对象
    var obj = { name:'xiaolin',age:24 }
    console.log(JSON.stringify(obj));  //'{"name":"xiaolin","age":24}'
    
    //json对象转js对象
    var jsonObj = '{ "name":"xiaolin","age":"24" }'
    console.log(JSON.parse(jsonObj));  //{name: 'xiaolin', age: '24'}
    
    //js数组转json数组
    var arr = [1,2,3,4,5,6]
    console.log(JSON.stringify(arr));  //'[1,2,3,4,5,6]'
    
    //json数组转js数组
    var jsonArr = '[1,2,3,4,5,6]'
    console.log(JSON.parse(jsonArr));  //[1,2,3,4,5,6]
    
  • 判断数据类型

    //1. typeof可判断undefined number string boolen function
    console.log(typeof(undefined))  //undefined 
    console.log(typeof(24))  //number
    console.log(typeof('xiaolin'))  //string
    console.log(typeof(true ))  //boolean
    console.log(typeof(Function))  //function
    
    //2.a instanceof b(判断a是不是b的实例,判断对象的具体类型)
    function People() {
      return
    }
    function Color() {
      return
    }
    var p1 = new People()
    var c2 = new Color()
    console.log(p1 instanceof People);  //true
    console.log(c2 instanceof Color);  //true
    console.log(c2 instanceof People);  //false
    
    console.log([1,2,3] instanceof Array);  //true
    
    //3.===,全等符可判断undefined null
    let a = null
    console.log(a === null);  //true
    
    let a = undefined
    let b
    console.log(a === undefined);  //true
    console.log(b === undefined);  //true
    
    //4.其它
    console.log(Array.isArray([1,2,3]));  //true