美文网首页WEB前端程序开发
js基础中不熟悉的点

js基础中不熟悉的点

作者: jdkwky | 来源:发表于2019-02-21 14:20 被阅读2次
    1. 亦或

    给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次。找出那个只出现了一次的元素。

    亦或:如果a,b两个值相同则亦或为0,如果不同则亦或为1

    1 ^ 1 = 0 
    1 ^ 0 = 1
    0 ^ 1 = 1
    0 ^ 0 = 0
    3 ^ 3 = 0 
    
    for(let i = 1 , len = nums.length;i < len; i ++){
      nums[ 0 ] ^ = nums[ i ]  
    }
    return nums[0]
    

    ? 结题答案中有用map数组比我用for循环计算时间少,why?

    可能是网络延时!!!!

    for循环的性能应该是最好的

    1. Array: map forEach

    map 和forEach都接受两个参数,第一个参数必填是个函数,第二个参数选填,作用是改变函数中this指向

    var name = 'wky'
    var a = { name = "yc" }
    var b = [1,3,4]
    b.map(function(val,index){
        return val + this.name
    }) 
    // 输出 ['1wky','3wky','4wky']
    
    b.map(function(val,index){
        return val + this.name
    },a)
    
    //输出 [ '1yc', '3yc','4yc' ]
    
    
    // 注:箭头函数this指向不变,仍指向父级中this指向
    
    b.map(val =>{ return val + this.a },a)
    
    // 输出输出 ['1wky','3wky','4wky']
    
    
    1. ? undefined == null true

      0 == undefined false

      ''== undefined false

      0 == null false

      '' == null false

    详见末尾宽松相等

    1. 基础类型

    字符串布尔类型都有方法,是因为使用对应的变量时,编译器会将其装箱成对应的对象类型,例如 var s = 'test',如果使用s变量时会将s = new String(s)进行封装,一旦属性引用结束,这个新创建的对象就会被销毁

    var s = 'test';
    s == new String(s)  // true
    s.len = 4
    s.len   // undefined
    
    1. arguments 和 function

      1.1 函数形参和实参
      在函数体中存在一个形参的引用,指向当前传入的实参列表,通过它可以获得参数的值

      1.2 函数体内this指向
      在严格模式中this 指向 undefined

      1.3 arguments

      1. arguments 是指向实参对象的引用
      2. arguments中的数组 与形参是别名的关系
      3. 严格模式下 arguments是个保留字,并且不能被重新赋值
      4. 非严格模式下 arguments是个标识符, 能被修改
      function test(){ 'use strict'; console.log( arguments ); arguments = 1 }
      
      // 报错 Uncaught SyntaxError: Unexpected eval or arguments in strict mode
      
      function test(){ arguments =2; console.log( arguments ); arguments = 1 }
      
      // arguments 输出为2
      

      1.4 闭包

      关联到闭包的作用域链都是活动的,嵌套的函数不会讲作用域内的私有成员复制一份,也不会对所绑定的变量生成静态快照。

      1.5 函数属性、方法和构造函数

      1. 函数length和函数实际参数的length
      function check(a, b ,c){
          console.log(arguments.length); // 实际参数个数
          console.log(arguments.callee.length); // 函数期待参数个数
      }
      
      
      1. call 和 apply方法

      call 和 apply方法 第一个参数的作用是改变函数体中this的指向,第二个参数是参数,可传可不传

          var obj = { 
              test: function(){console.log(this.a)},
              a: '10' 
          }
          var a = 20;
          obj.test.call(null); // 20
          obj.test.call(obj); // 10
          
          Object.prototype.toString.call([]) // 改变的是toString中this的指向
          
      
      

      apply 参数传入的是个数组,但是会将数组参数和函数形参一一对应

      function testArray(a){ console.log(a) }
      testArray.apply(null,[1,3])
      <!--输出 1-->
      
      function test(a,b){ console.log(a);console.log(b) }
      test.apply([1,3])
      <!--输出  1, 3-->
      

      Object.prototype.toString返回数据解析

      当检测Array实例时, Array.isArray 优于 instanceof,因为Array.isArray能检测iframes

      var iframe = document.createElement('iframe');
       document.body.appendChild(iframe);
       xArray = window.frames[window.frames.length-1].Array;
       var arr = new xArray(1,2,3); // [1,2,3]
       
       // Correctly checking for Array
       Array.isArray(arr);  // true
       // Considered harmful, because doesn't work though iframes
       arr instanceof Array; // false
      
      1. 第一个参数改变函数内部this指向的函数还有Array类中的方法:

        1. forEach
        2. filter
        3. findIndex
        4. find
        5. map

        reduce 如果在空数组上调用reduce必须给一个默认值不然就会报错

       const array = [];
       const reducer = (c, a) => c + a ;
       array.reduce(reducer)
       <!--VM1172:1 Uncaught TypeError: Reduce of empty array with no initial value-->
       <!--    at Array.reduce (<anonymous>)-->
       <!--    at <anonymous>:1:7-->
       <!--(anonymous) @ VM1172:1-->
       array.reduce(reducer,0)
       <!--0-->
      

      array.length 值是一个无符号32位整数

      1. bind : 第一个参数改变this指向,第二个是传入的参数
      2. 构造函数 Function构造函数创建的函数并不使用词法作用域,相反,函数体代码的编译总是会在顶层函数执行.
      function con (){
           const local = 'local';
           return new Function ('return local');
       }
       const local = 'global';
       con()(); // global
       
       function con(){
       var scope1 = 'local';
           return function(){
               console.log( scope1 );
           }
       }
       var scope1 = 'global';
       
       con()(); // 输出 local
      
    1. promise promise.all await async generator setTimeout

      1. setTimeout (function,delay,param)
      function test(value){ console.log(value) }
      setTimeout(test,500,10) // 500ms之后 输出10
      // 参数是待执行函数的参数
      
      1. Promise.resolve()

        需要将现有对象转换为Promise对象

        1. 参数是一个Promise实例
          如果参数是一个Promise实例,那么Promise.resolve将不做任何修改、原封不动的返回这个实例
        2. 参数是一个thenable对象
          thenabel对象是指具有then方法的对象,例如:
        let thenable = {
            then:(resolve,reject)=>{
                return resolve(21);
            }
        }
        

        Promise.resolve()方法将这个对象转换为Promise对象,并立即执行then方法

        let thenable = {
            then:(resolve,reject)=>{
                return resolve(21);
            }
        }
        let p1 = Promise.resolve(thenable)
        
        1. 参数不是具有then的对象,或者根本不是对象
          返回一个新的promise对象
        2. 不带有任何参数
          直接返回一个Promise对象
      2. Promise原理(暂时还是有点懵,可能需要在看看?)

      function Promise(fn){
      var state = "pending";
      var value = null;
      var callbacks = [];
      this.then = function(onFulfilled){
      
          return new Promise(function( resolve ){
              handle({
                  onFulfilled: onFulfilled || null,
                  resolve: resolve
              });
          })
      };
      function handle(callback){
          if( state == 'pending' ){
              callbacks.push(callback);
              return ;
          }
          if(!callback.onFulfilled){
              callback.resolve(value);
              return;
          }
          var ret = callback.onFulfilled(value);
          callback.resolve(ret);
      }
      function resolve(newValue){
          if(newValue && (typeof newValue ==='object' || typeof  newValue ==='function')){
              var then = newValue.then;
              if(typeof then ==='function'){
                  then.call(newValue,resolve);
                  return;
              }
          }
          state = 'fulfilled';
          value = newValue;
          setTimeout(function(){
              callbacks.forEach(function(callback){
                  handle(callback);
              })
          },0);
      }
      fn(resolve);
      }
      
    2. generator 自执行函数

    function co(gen){
        var g = gen();
        var t = g.next();
        function next(res){
            console.log(res);
            if(res.done) return ;
            if(typeof g.next !='function') return;
            if(res.value instanceof Promise){
                res.value.then(value =>{
                    res = g.next(value);
                    next(res);
                })
            }
        }
        next(t)
    };
    

    注意: g.next(value) 这个value对应的值是上一个yield的返回值

    1. JSON.stringify 接受三个参数 (value,replace,space)

      1. replace 是函数
      JSON.stringify({name:'name',function(key,value){key // key  value // 值 }})
      
      1. replace是数组
      JSON.stringify({1:1,2:1,3:1,5:1},[1,5]) // "{ "1":1,"5":1 }"
      
    2. for of 只能遍历存在 Symbol.iterator接口的数据结构,对象不存在这个接口,所以只能通过手动添加这个遍历器接口

    var Obj = { name:'name',age:18 ,info:{ name:'infoName',age:'infoAge' }};
    Object.defineProperty(Obj,Symbol.iterator,{
        value:function(){
            var o = this;
            var idx = 0;
            var ks = Object.keys(o);
            return {
                next:function(){
                    return {
                        value: o[ks[idx++]],
                        done: idx > ks.length
                    }
                }
            }
        },
        enumerabel: false,
        writable: false,
        configurable: true,
        
    });
    for(let value of Obj){
        console.log(value);
    }
    // 输出    name  18    info:{ name:'infoName', age:'infoAge' }
    
    1. 原型 继承

      1. Object.create模拟实现
      Object.create = function (o){
          var F = function(){};
          F.prototype = o;
          return new F();
      }
      
    2. 强制类型转换

      1. JSON.stringify转换规则(ToString)
      1. 字符串、数字、布尔值和null的转换规则和ToString一致
      2. 如果传递给JSON.stringify的对象中定义了toJSON方法,那么该方法会在字符串化前调用,以便将对象转化成安全的JSON值
      var a ={ 
          name:'wky',
          age:10,
          toJSON:function(){ 
              return this.name
              } 
      }
      JSON.stringify(a) ;// ""wky""
      
      1. ToNumber

      为了将值转换为基本数据类型,抽象操作ToPrimitive会先检查该值是否有valueof()方法,没有然后在检查是否有通toString()方法

      var a = { 
          valueOf:function(){ return '23' },
          toString:function(){ return '12' } 
      }
      
      Number(a) // 23
      
      
      1. 宽松相等

        1. 字符串和数字之间相等的比较

        字符串转换成数字

        '42' == 42 // true Number('42') == 42
        
        
        1. 其他类型和Boolean类型的比较

        boolean类型转换成number

        '42' == true  // false   '42' == Number(true)1
        
        1. null 与undefined对比 (相等)
        2. 对象与非对象的比较

        ToPrimative(Obj) == 字符串或者数字

        42 == [42] // true
        
        
    3. 如何判断对象是原生的还是非原生对象

    原生对象 执行toString()方法之后函数中会出现'native code'函数

    相关文章

      网友评论

        本文标题:js基础中不熟悉的点

        本文链接:https://www.haomeiwen.com/subject/iymryqtx.html