题目笔记(闭包,深复制和浅复制,原生js实现Promise)

就面试笔试题的一些笔记:

  • 闭包( 实现add(2)(5) )
  • 深复制和浅复制
  • 原生js实现Promise

△ –>闭包知识:

实现add(2)(5)

function add (x) {
return function(y) { return x + y; };
}

△ –>深复制和浅复制:

深拷贝 与 浅拷贝: 循环引用和函数是不能通过 stringify 进行深拷贝的

  • 对于循环引用和函数是无法通过stringify和parse的方法进行深拷贝的,关于循环引用,可以通过查找循环点来断掉这个循环,再进行深拷贝。

遇到的问题 :
* 解决数组浅拷贝的问题:
直接等于 = arr1=arr2;
slice和concat方法可以进行简单素组的深拷贝
由于数组内部属性值为引用对象,因此使用slice和concat对对象数组的拷贝,整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址。
因此,slice和concat这两个方法,仅适用于对不包含引用对象的一维数组的深拷贝

  • 解决数组深拷贝的问题:
    也是通过 stringify 和 parse 的方法进行深拷贝,

  • 解决深拷贝的问题:
    先把数据进行stringify转换 ,再进行一次parse转换。
    JSON.stringify() 方法是将一个JavaScript值(对象或者数组)转换为一个 JSON字符串
    JSON.parse() 方法解析JSON格式数据并构造一个由字符串描述的JavaScript对象/值

  • 总结:

    1. 浅拷贝相当于引用地址的复制,两个变量指针是共享(引用)同一个对象。obj1 === obj2
    2. 深拷贝相当于为另外一个对象开辟内存空间,并进行递归复制内部属性。两个对象的引用地址是不一样的(即不是引用同一个对象)。obj1 !== obj2
    3. 可以通过”赋值操作符”、Object.assign()、数组遍历赋值等实现浅拷贝。
    4. 可以通过自定义代码、JSON对象的方法(JSON.parse和JSON.stringify)、JQuery.extend()等实现深拷贝。
    5. 目前来说,并没有统一的标准方法来解决”循环引用”,从而实现真正的深拷贝。
  • 比如 react 里面有大量的对象复制,用 immutable 就很好。
    对付 deep clone, 最好的办法是抛弃需要 deep clone 的代码

  • 实际开发中 除了通过 stringify 和 parse 的方法进行深拷贝,
    eg:
    let item = JSON.parse(JSON.stringify(temp));
    item[‘recharge_principal’] = FormatMoneyByM(temp[‘recharge_principal’]);
    为此还采用了其他方式对数据做了处理,
    为了避免改变数据的值,直接将通过格式化函数后,加入数组中。不采用中间变量来传递值。
    eg:
    let temp = data.list [ key ] || { } ;
    principal_arr.push ( CalculateMoneyByMm ( temp[ ’ principa l’ ] || 0 ) );

△ –> 用原生js实现promise:

ES6中Promise可以说很大情况下改善了异步回调的嵌套问题

第一:Promise构造函数接受一个函数作为参数,函数里面有两个参数resolve和reject分别作为执行成功或者执行失败的函数
var promise=new Promsie(function(resolve,rejec){
    if(/*异步执行成功*/){
        resolve(value);
    }else{
        reject(error);
    }
})
第二:可以通过then设置操作成功之后的操作,接受两个函数作为参数
.then(function(){
    //回调执行成功之后的操作
},function(){
    //回调执行失败之后的操作,可以没有
});

Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected

function Promise(){
    this.status='pending'; //待定
    this.msg='';
    var process=arguments[0];
    var that=this;
    process(function(){
        that.status='resolve';
        that.msg=arguments[0];
    },function(){
        that.status='reject';     
        that.msg=arguments[0];           
    });
    return this;
}

Promise.prototype.then=function(){
    if(this.status=='resolve'){
        arguments[0](this.msg);
    }
    if(this.status=='reject '&& arguments[1]){
        arguments[1](this.msg);
    }
}

//测试
var promise =new Promise(function(resolve,reject){
    resolve('success!!!');
});
promise.then(function(success){
    console.log('success');
},function(){
    console.log('failed');
});

以上只是最基本的实现,在代码结构结构和容错方面没有进行考虑。
Promise对象的缺点:
1、无法取消Promise,一旦新建它就会立即执行,无法中途取消。
2、如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
3、当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。

/* 我们要满足状态只能三种状态:PENDING,FULFILLED,REJECTED三种状态,
且状态只能由PENDING=>FULFILLED,或者PENDING=>REJECTED */
            var PENDING = 0;
            var FULFILLED = 1;
            var REJECTED = 2;
/* value状态为执行成功事件的入参,deferreds保存着状态改变之后的需要处理的函数以及promise子节点,
构造函数里面应该包含这三个属性的初始化 */
            function Promise(callback) {
                this.status = PENDING;
                this.value = null;
                this.defferd = [];
                setTimeout(callback.bind(this, this.resolve.bind(this), this.reject.bind(this)), 0);
            }

            Promise.prototype = {
                constructor: Promise,
                //触发改变promise状态到FULFILLED
                resolve: function (result) {
                    this.status = FULFILLED;
                    this.value = result;
                    this.done();
                },
                //触发改变promise状态到REJECTED
                reject: function (error) {
                    this.status = REJECTED;
                    this.value = error;
                },
                //处理defferd
                handle: function (fn) {
                    if (!fn) {
                        return;
                    }
                    var value = this.value;
                    var t = this.status;
                    var p;
                    if (t == PENDING) {
                         this.defferd.push(fn);
                    } else {
                        if (t == FULFILLED && typeof fn.onfulfiled == 'function') {
                            p = fn.onfulfiled(value);
                        }
                        if (t == REJECTED && typeof fn.onrejected == 'function') {
                            p = fn.onrejected(value);
                        }
                    var promise = fn.promise;
                    if (promise) {
                        if (p && p.constructor == Promise) {
                            p.defferd = promise.defferd;
                        } else {
                            p = this;
                            p.defferd = promise.defferd;
                            this.done();
                        }
                    }
                    }
                },
                //触发promise defferd里面需要执行的函数
                done: function () {
                    var status = this.status;
                    if (status == PENDING) {
                        return;
                    }
                    var defferd = this.defferd;
                    for (var i = 0; i < defferd.length; i++) {
                        this.handle(defferd[i]);
                    }
                },
                /*储存then函数里面的事件
                返回promise对象
                defferd函数当前promise对象里面
                */
                then: function (success, fail) {
                   var o = {
                        onfulfiled: success,
                        onrejected: fail
                    };
                    var status = this.status;
                    o.promise = new this.constructor(function () {

                    });
                    if (status == PENDING) {
                        this.defferd.push(o);
                    } else if (status == FULFILLED || status == REJECTED) {
                        this.handle(o);
                    }
                    return o.promise;
                }
            };

你可能感兴趣的:(js,工作分享)