javascript部分

//generator yield 解析

function *test(){
   console.log('a');
   let data1 = yield 22;
   console.log(data1);
   return 'done'
}

var obj = test();

var obj1 = obj.next()
//此时控制台打印'a',并给obj1 => {done: false, value: 22}

var obj2 = obj.next('in')
//此时控制台打印'in',并给obj2 => {done: true, value: "done"}

//es7 提供了async await 和提供同步方式编写代码

//大概实现原理

function runner(_gen){
  return new Promise((resolve, reject)=>{
    var gen=_gen();

    _next();
    function _next(_last_res){
      var res=gen.next(_last_res);

      if(!res.done){
        var obj=res.value;

        if(obj.then){
          obj.then((res)=>{
            _next(res);
          }, (err)=>{
            reject(err);
          });
        }else if(typeof obj=='function'){
          if(obj.constructor.toString().startsWith('function GeneratorFunction()')){
            runner(obj).then(res=>_next(res), reject);
          }else{
            _next(obj());
          }
        }else{
          _next(obj);
        }
      }else{
        resolve(res.value);
      }
    }
  });
}


//使用
runner(function *(){
  alert('欢迎哈');

  let arr=yield $.ajax({url: 'data/1.txt', dataType: 'json'});

  alert('接收到了数组'+arr);

  let json=yield $.ajax({url: 'data/2.txt', dataType: 'json'});

  alert('json也读完了');

  console.log(json);
});
//运算优先级
var a = {n: 1};
var b = a;
a.x = a = {n: 2};

a.x     // undefined
b.x   // {n:2}

//js的赋值运算顺序永远都是从右往左的,不过由于“.”是优先级最高的运算符,所以这行代码先“计算”了a.x,所以对象A多了个值为undefined的x

//这里对象A指{n: 1}, 对象B指{n: 2}

//由于( .  运算符最先计算)一开始js已经先计算了a.x,便已经解析了这个a.x是对象A的x,所以在同一条公式的情况下再回来给a.x赋值,也不会说重新解析这个a.x为对象B的x

 this绑定的硬绑定和软绑定实现

背景: 硬绑定可以把this强制绑定到指定的对象(`new`除外),防止函数调用应用默认绑定规则。但是会降低函数的灵活性,使用**硬绑定之后就无法使用隐式绑定或者显式绑定来修改this**。

var a = {b:1};
var b = {b:2}
function func(){
  console.log(this.b)
}
var bind1 = func.bind(a)

bind1()  //1

bind1.apply(b) //1

var copybind1 = bind1.bind(b)
copybind1() //1

软绑定实现原理:给默认绑定指定一个全局对象和undefined以外的值**,那就可以实现和硬绑定相同的效果

// 默认绑定规则,优先级排最后
// 如果this绑定到全局对象或者undefined,那就把指定的默认对象obj绑定到this,否则不会修改this
if(!Function.prototype.softBind) {
    Function.prototype.softBind = function(obj) {
        var fn = this;//对应要绑定的函数
        // 捕获所有curried参数
        var curried = [].slice.call( arguments, 1 ); //柯里化,预绑定参数
        var bound = function() {
            return fn.apply(
                (!this || this === (window || global)) ? 
                    obj : this,
                curried.concat.apply( curried, arguments ) //
            );
        };
        bound.prototype = Object.create( fn.prototype );//继承原型,避免绑定后得到的函数原型丢失
        return bound;
    };
}
function foo() {
    console.log("name:" + this.name);
}

var obj = { name: "obj" },
    obj2 = { name: "obj2" },
    obj3 = { name: "obj3" };

// 默认绑定,应用软绑定,软绑定把this绑定到默认对象obj
var fooOBJ = foo.softBind( obj );
fooOBJ(); // name: obj 

// 隐式绑定规则
obj2.foo = foo.softBind( obj );
obj2.foo(); // name: obj2 <---- 看!!!

// 显式绑定规则
fooOBJ.call( obj3 ); // name: obj3 <---- 看!!!

// 绑定丢失,应用软绑定
setTimeout( obj2.foo, 10 ); // name: obj

 this考题举例

var num = 1;
var myObject = {
    num: 2,
    add: function() {
        this.num = 3; // 隐式绑定 修改 myObject.num = 3
        // 严格模式下,报错。`TypeError: Cannot read property 'num' of undefined`
        // 即使非自执行函数,this也是window;这个不属于隐式绑定,容易误区
        (function() {
            console.log(this.num); // 默认绑定 输出 1
            this.num = 4; // 默认绑定 修改 window.num = 4
        })();
        console.log(this.num); // 隐式绑定 输出 3
    },
    sub: function() {
        console.log(this.num) // 因为丢失了隐式绑定的myObject,所以使用默认绑定 输出 4
    }
}
myObject.add(); // 1 3
console.log(myObject.num); // 3
console.log(num); // 4
var sub = myObject.sub;//  丢失了隐式绑定的myObject
sub(); // 4
var name = 'window'

function Person (name) {
  this.name = name;
  this.show2 = () => console.log(this.name)
}

var personA = new Person('personA')

personA.show2() //personA
personA.show2.call(personB) // personA


//另一种形式
var name = 'window'

var person1 = {
  name: 'person1',
  show2: () => console.log(this.name)
}
var person2 = { name: 'person2' }

person1.show2() //window
person1.show2.call(person2) //window

//结论
// 箭头函数的this无法通过bind,call,apply来**直接**修改(可以间接修改)

 实现一个深拷贝

//没有考虑symbol和递归爆栈
function cloneDeep(source, hash = new WeakMap()) {
    if (typeof source !== 'object') return source;

    let target = Array.isArray(source) ? [] : {}
    //解决循环引用和引用丢失
    if (hash.has(source)) {
        console.log('in')
        return hash.get(source)
    }

    hash.set(source, target)

    for (let item in source) {
        if (source.hasOwnProperty(item)) {
            if (typeof source[item] === 'object' && source[item] != null) {
                target[item] = cloneDeep(source[item], hash)
            } else {
                target[item] = source[item]
            }
        }

    }
    return target

}
//参考链接https://github.com/yygmind/blog/issues/29

 node与浏览器的event loop 区别

https://juejin.im/post/5d5b4c2df265da03dd3d73e5 (浏览器的事件循环)

https://juejin.im/post/5c337ae06fb9a049bc4cd218#heading-12 (比较)

// node的运行环境
console.log('start')
setTimeout(() => {
  console.log('timer1')
  Promise.resolve().then(function() {
    console.log('promise1')
  })
}, 0)
setTimeout(() => {
  console.log('timer2')
  Promise.resolve().then(function() {
    console.log('promise2')
  })
}, 0)
Promise.resolve().then(function() {
  console.log('promise3')
})
console.log('end')
//start=>end=>promise3=>timer1=>timer2=>promise1=>promise2

// 浏览器的运行环境
//start=>end=>promise3=>timer1=>promise1=>timer2=>promise2

一开始执行栈的同步任务(这属于宏任务)执行完毕后(依次打印出start end,并将2个timer依次放入timer队列),会先去执行微任务(这点跟浏览器端的一样),所以打印出promise3

然后进入timers阶段,执行timer1的回调函数,打印timer1,并将promise.then回调放入microtask队列,同样的步骤执行timer2,打印timer2;这点跟浏览器端相差比较大,timers阶段有几个setTimeout/setInterval都会依次执行,并不像浏览器端,每执行一个宏任务后就去执行一个微任务

如果是node11版本一旦执行一个阶段里的一个宏任务(setTimeout,setInterval和setImmediate)就立刻执行微任务队列,这就跟浏览器端运行一致

如果是node10及其之前版本:要看第一个定时器执行完,第二个定时器是否在完成队列中

总结:

Node端,microtask 在事件循环的各个阶段之间执行

浏览器端,microtask 在事件循环的 macrotask 执行完之后执行

 

对constructor的理解

 

export 和 export default

export 导出的变量实际上仍然可以受到原来模块的控制。不单单本身模块的a值会变化, 使得其他模块中引入的 a 值发生改变

export default 导出的是值,导出的就是普通变量 a 的值,以后 a 的变化与导出的值就无关了,修改变量 a,不会使得其他模块中引入的 default 值发生改变。

 

 

posted @ 2019-02-17 22:02  潮哥  阅读(212)  评论(0编辑  收藏  举报