1. 程式人生 > >題目筆記(閉包,深複製和淺複製,原生js實現Promise)

題目筆記(閉包,深複製和淺複製,原生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實現Promise

就面試筆試題的一些筆記: 閉包( 實現add(2)(5) ) 深複製和淺複製 原生js實現Promise △ –>閉包知識: 實現add(2)(5) function add (x) { return functio

列表的使用2COPYCOPY循環列表步長切片

strong 全部 有一個 也有 內存地址 log 嚴重 mes 數值 name2=names.copy() 下面我看幾種奇怪的現象: 首先把源列表copy以後,把源列表第2個數值修改。那麽沒毛病。 如果源列表裏,還包含了一個子列表:這也沒毛病 如果我們這個時候修改子

python的複製拷貝拷貝的區別

在python中,物件賦值實際上是物件的引用。當建立一個物件,然後把它賦給另一個變數的時候,python並沒有拷貝這個物件,而只是拷貝了這個物件的引用 一般有三種方法, alist=[1,2,3,[“a”,“b”]] (1)直接賦值,傳遞物件的引用而已,原始列表

javascript的複製複製深度拷貝拷貝

<!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"><title>js深度複製淺顯複製</title> </head>

python的復制拷貝拷貝的區別(轉)

pla bsp space 數據 深拷貝 淺拷貝 deepcopy 拷貝 tro 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是拷貝了這個對象的引用 一般有三種方法, alist=[1,2,

python的復制拷貝拷貝的區別

一個 對象賦值 source 深拷貝 對象的引用 數據 拷貝 也會 方法 寫在前面: python中的.copy()拷貝和[:]拷貝皆為淺拷貝 在python中,對象賦值實際上是對象的引用。當創建一個對象,然後把它賦給另一個變量的時候,python並沒有拷貝這個對象,而只是

C 複製複製

分享一下我老師大神的人工智慧教程!零基礎,通俗易懂!http://blog.csdn.net/jiangjunshow 也歡迎大家轉載本篇文章。分享知識,造福人民,實現我們中華民族偉大復興!        

Python的賦值拷貝拷貝的區別

在python中,物件賦值實際上是物件的引用。當建立一個物件,然後把它賦給另一個變數的時候,python並沒有拷貝這個物件,而只是拷貝了這個物件的引用 一般有三種方法, alist=[1,2,3,["a","b"]]   (1)直接賦值,傳遞物件的引用而已,原始列表改變,被

結合多個例項深入理解js拷貝拷貝多種方法實現物件的拷貝

親們為什麼要研究深拷貝和淺拷貝呢,因為我們專案開發中有許多情況需要拷貝一個數組抑或是物件,但是單純的靠=“賦值”並不會解決所有問題,如果遇到引用型別的物件改變新賦值的物件會造成原始物件也發生同樣改變,而要去除影響就必須用到深拷貝,深拷貝,對於引用物件需要進行深拷貝才會去除影響。如果是值型別直接“=”

談物件的複製複製的區別。

  場景   當你的元件裡需要用到同一個資料,但身負不同的責任。   舉個例子:vue的雙向繫結   你在與後端的互動中請求回來的資料,res,  let a = res; let b = res;  因為是會用到checkbox,在外層的列表裡選中資

C++的拷貝建構函式、operator=運算子過載拷貝拷貝、explicit關鍵字

1、在C++編碼過程中,類的建立十分頻繁。 簡單的功能,當然不用考慮太多,但是從進一步深刻理解C++的內涵,類的結構和用法,編寫更好的程式碼的角度去考慮,我們就需要用到標題所提到的這些內容。 最近,在看單例模式,覺得十分有趣,然而如果想要掌握單例模式,就必須掌握這些內容。下

ES6(JavaScript)的複製複製

React中,我們會遇到一個有趣的問題,那就是物件的複製,為什麼說有趣,是因為直覺和結果差距很大。 我們看一下這個例子: let a={tile:'深複製'}; let b=a; a.title='淺複製'; 那麼我們會獲得兩個物件,一個a,一個b,a的title是淺複製,

Java物件的複製複製

原文連結 我們在編碼過程經常會碰到將一個物件傳遞給另一個物件,java中對於基本型變數採用的是值傳遞,而對於物件比如bean傳遞時採用的引用傳遞也就是地址傳遞,而很多時候對於物件傳遞我們也希望能夠象值傳遞一樣,使得傳遞之前和之後有不同的記憶體地址,在這種情況下

如何理解原型模式中的複製複製

    找工作之前製作簡歷時,需要做很多份簡歷,而且簡歷的格式是一樣的,也就意味著要做很多重複性的工作。在程式設計過程中,遇到重複性工作多的時候,貼上複製是最快的解決辦法。但是一旦這些程式碼需要修改時

Java中clone方法以及複製複製

Java中處理基本資料型別(如:int , char , double等),都是採用按值傳遞的方式執行,除此之外的其他型別都是按照引用傳遞(傳遞的是一個物件的引用)的方式執行。物件在函式呼叫時和使用“=”賦值時都是引用傳遞。 Java中clone方法的作用是為了在現實程式

面試:C++的複製複製(轉)

物件的構造,也可以由複製建構函式完成,即用一個物件的內容去初始化另一個物件的內容。此時,若物件使用了堆空間(注意和“堆物件”區分),就有深、淺複製的問題,不清楚則很容易出錯。 什麼是淺複製 預設複製建構函式:用一個物件的內容初始化另一個同類物件,也稱為預設的

C 複製複製

                物件的複製   對於普通型別的物件來說,它們之間的複製是很簡單的,例如:int a=88;int b=a;double f=3.12;double d(f);  而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種資料成員。下面看一個類物件複製的簡單例子。#includ

C++複製複製

物件的複製   對於普通型別的物件來說,它們之間的複製是很簡單的,例如:int a=88; int b=a; double f=3.12; double d(f);  而類物件與普通物件不同,類物件內部結構一般較為複雜,存在各種資料成員。下面看一個類物件複製的簡單例子。#in

python的複製複製

# -*- coding:UTF-8 -*- #此次練習主要是討論物件的淺複製和深複製 import copy #淺複製一個object有三種方式:1、slice操作; # 2、copy模組的copy函式; #

拷貝拷貝及幾種實現方法

rgb bsp for ace onos 都是 UNC get con 討論深拷貝與淺拷貝之前,要先回顧一下值傳遞與引用傳遞: 值傳遞: var a = 10; var b = a; b++; //console.log(a,b)//a:10 b:11 引用傳遞: v