js計算練習


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<script>
    // function sum(...x) {
    //     var s = 0;
    //     for(var i = 0;i<x.length;i++){
    //         // s ++
    //         s += x[i];
    //     }
    //     var sum_fn = function (...y) {
    //         for(var i = 0;i<y.length;i++){
    //             //s++
    //             s +=y[i];
    //         }
    //         return sum_fn;
    //     }
    //     sum_fn.valueOf = function(){
    //         return s;
    //     }
    //     return sum_fn;
    // }

    function sum (...x) {
        var s = 0;
        for (var i = 0;i<x.length;i++){
            s+=x[i];
        }
        var sum_fn = function(...y) {
            for (var i = 0;i<y.length;i++){
                s +=y[i];
            }
            return sum_fn;
        }
        sum_fn.valueOf = function(){
            return s;
        }
        return sum_fn;
    }
    function sum (...x){
        var s = 0;
        const add = arr=>arr.forEach(a=>s+=a);
        add(x);
            var sum_fn = function(...y) {
                add(y);
                return sum_fn;
            }
        sum_fn.valueOf = function(){
            return s;
        } 
        return sum_fn;
    }
    console.log(sum(1)(2)(3)(4)(5).valueOf())
    console.log(sum(1,2,3,4)(5).valueOf())
    console.log(sum(1,2,3,4)(5).valueOf())
    console.log(sum(1,2,3)(4)(5).valueOf())
    console.log(sum(1,2)(3,4)(5).valueOf())
</script>
<body>
    
</body>
</html>
============

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
// function add(...args){
//             var fn = args[0];
//             console.log(args)
//             var arr = fn();
//             var sum = 0;
//       if (typeof arr == "number"){
//                 sum = arr;
//             }
//             else {
//         sum = arr[0];
//                 for(var i = 0;i<arr.length - 1;i++){
//                // console.log(arr[i])
//                 sum += arr[i+1];
        
//             }
//       }
//             for(var i =1;i<args.length;i++){
//                // console.log(args[i])
//                 sum += args[i]
//             }
//             return function(){
//                 return sum
//             }
//         }

//          function subtract(...args){
//             var fn = args[0];
//             console.log(args)
//             var arr = fn(); //arr []
//             var sum ;
//             if (typeof arr == "number"){
//                 sum = arr;
//             }
            
//             else {
//         sum = arr[0];
//                 for(var i = 0;i<arr.length - 1;i++){
//                // console.log(arr[i])
//                 sum -= arr[i+1];
        
//             }
//       }
//             for(var i =1;i<args.length;i++){
//                // console.log(args[i])
//                 sum -= args[i]
//             }
//             return function(){
//                 return sum
//             }
//         }


//     function num(x){
//         var arr = [];
//         arr.push(x);
//         var num_fn = function(x){
//             if(!x) return arr;
//             else{
//                 arr.push(x);
//                 return num_fn;
//             }
//         }
//         return num_fn;
//     } 

//     console.log(add(add(num(3)(4)(5)),2,4)()) //6



    function mathss(args,q){
    var fn = args[0];
            console.log(args)
            var arr = fn();
            var sum = 0;
      if (typeof arr == "number"){
                sum = arr;
            }
            else {
        sum = arr[0];
                for(var i = 0;i<arr.length - 1;i++){
               // console.log(arr[i]) 
               q=1? sum += arr[i+1]:sum -= arr[i+1]
        
            }
      }
            for(var i =1;i<args.length;i++){
               // console.log(args[i])
                q=1?sum += args[i]:sum -= args[i]
            }
            return function(){
                return sum
            }
}


    function add(...args){
       return mathss(args,1)
    }
    
    function subtract(...args){
       return mathss(args,0) 
    }

     function num(x){
        var arr = [];
        arr.push(x);
        var num_fn = function(x){
            if(!x) return arr;
            else{
                arr.push(x);
                return num_fn;
            }
        }
        return num_fn;
    }

    console.log(add(add(num(3)(4)(5)),2,4)()) //6



   
    </script>
</body>
</html>
===============

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        function sum(...x){
            var s= 0;
            for(var i = 0;i<x.length;i++){
                s=x[i];
            }
            var sum_fn=function(...y){
                for(var i =0;i<y.length;i++){
                    s+=y[i];
                }
                return sum_fn
            }
            sum_fn.valueOf = function(){
                return s;
            }
            return sum_fn; 
        }

        function sum(...x){
            var s = 0;
            for(var i = 0;i<x.length;i++){
                s +=x[i]
            }
            var sum_fn = function(...y){
            
            }



        function num(x){
            return function(a){
                return function(b){
                    return function(c){

                    }
                }
            }
        }

        function nun(x){
            var arr = [];
            arr.push(x);
            var num_f=function(x){
                if(!x) return arr;
                else {
                    arr.push(x);
                    return num_f; 
                }
            }
            return num_f;
        }

        function num (x){
            var arr = [];
            arr.push(x);
            var num_fn = function(x){
                if(!x) return arr;
                else {
                    arr.push(x);
                    return num_fn;
                }
            }
            return num_fn;
        }

        function add(...args){
            var fn = args[0];
        }



        function add (...args ){
            var fn =args [0];
            var arr = fn();
            for(var i =0;i<arr.length;i++){
                console.log(arr[i])
            }
            for(var i =1;i<args.length;i++){
                console.log(args[i])
            }
            return function(){
                return
            }
        }
        function num(x){
            var arr = [];
            ar.push(x);
            var num_fn = function (x) { 
                if(!x) return arr ;
                eles {
                    arr.push(x);
                    return num_fn;
                }
            }
            return num_fn;
        }
        add(num(4)(6),2,4,6)



        function add(...args){ 
            var fn = args[0]; 
            var arr = fn();
            var arrr = fn();
            for(var i  = 0;i<arr.length;i++){

            }
            }
    </script>
</body>
</html>
=======

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <!-- 閉包 -->
    <!-- 函數作爲返回值 -->
    <!-- 高階函數除了可以接受函數作爲參數外,還可以把函數作爲返回值返回 -->
    <script>
        // function sum(arr){
        //     debugger;
        //     return arr.reduce(function(x,y) {
        //         return x+y
        //     })
        // }
        // console.log(sum([1,2,3,4,5]))

        // 但是,如果不需要立刻求和,而是在後面的代碼中,根據需要在計算怎麼辦?
        // 可以不返回求和的結果,返回求和的函數
        function lazzy_sum(arr) {
            var sum = function(){
                return arr.reduce(functon(x,y){
                    return 
                })
            }
        }
    </script>
</body>
</html>
============

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        // var two = function(x){
        //     typeof x == 'function'?x(2) :2;
        // }
        // var one = function(x){
        //     typeof x == 'function'?x(1):1;
        // }
        // var three = function(x){
        //     typeof x == 'function'?x(3):3;
        // }
        var two = x=>typeof x =='function'?x(2):2; 
        var one = x=>typeof x =='function'?x(1):1;
        var tthreewo = x=>typeof x =='function'?x(3):3;
        var add = function(a){
            return function(b){
                return a + b;
            }
        }
       console.log( one(add(two())))
    </script>
</body>
</html>
==================

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
<body>
    <script>
        function checkName(){

        }
        function checkEmail(){

        }
        function checkPassword(){

        }
        //這種在用的時候需要提前聲明
        var checkName = function(){
            //驗證姓名
        }
        var checkEmail = function(){
            //驗證郵箱密碼
        }
        var checkPassword = function(){
            //驗證密碼
        }
        //對象有屬性和方法,而如果我們要訪問它的屬性或者方法時,可以通過點語法向下遍歷
        //查詢得到。我們可以創見一個檢測對象,然後把我們的方法放在裏面
        var ChckObject = {
            checkName:function(){
                //驗證密碼
            },
            checkEmail:function(){
                //驗證郵箱
            },
            checkPassword:function(){
                //驗證密碼
            }
        }
        //此時我們將所有的函數作爲CheckObjectd對象的方法,這樣我們就有一個對象,而我們想要
        //使用它很簡單,比如檢測姓名CheckObject.checkName(),只是我們原來使用的函數式前面
        //多了一個對象名稱

        //既然我們可以通過.的語法來使用,是不是也可以通過.的語法創建呢?
        //是的前提是你要聲明一個對象,然後給它添加方法,當然在js中函數也是對象
        var CheckObject = function(){

        }
        CheckObject.checkName=function(){
            //驗證姓名
        }
        CheckObject.checkEmail=function(){
            //驗證郵箱
        }
        CheckObject.checkPassword=function(){
            //驗證密碼
        }
        //使用和前面的方式是一樣的,比如CheckObiect.checkName(),現在雖然能滿足你的需求
        //別人想用你寫的對象方法時就有一些麻煩了,因爲這個對象不能複製一份,或者說這個對象
        //類再用new個關鍵字創新的對象時,新創建的對象是不能繼承這個方法的

        //真假對象
        //如果你簡單地複製一下,你可以將方法放在一個函數對象中。
        var CheckObject = function(){
            return {
                checkName:function(){
                    //驗證姓名
                },
                checkEmail:{
                    //驗證郵箱
                },
                checkPassword:{
                    //驗證密碼
                }
            }
        }

        var a = CheckObject();
        a.checkEmail();
        //雖然通過創建了新對象完成了我們的需求,但是他不是一個真正意義上類的創建方式,並且創建
        //的對象a和對象CheckObject沒又任何關係(返回出來的對象本身就與Object對象無關)
        var ChckObject=function(){
            this.checkName=function(){
                //驗證名字
            }
            this.checkEmail=function(){
                //驗證郵箱
            }
            this.checkPassword=function(){
                //驗證密碼
            }
        }
        //像上面這樣就可以用CheckObject類創建出來的對象了
        //我們把所有的方法放在函數內部了,通過this定義的,所以每一次通過new關鍵字創建
        //新對象的時候,新創建的對象都會對類的this上的屬性進行復制。所以這些新創建的
        //對象都會有一套方法,然而有時候這麼做消耗是很奢侈的,我們需要處理一下
        var CheckObject=function(){};
        CheckObject.prototype={
            checkName:function(){

            },
            checkEmail:function(){

            },
            checkPassword:function(){

            }
        }
        //但有一點要記住,這兩種方式不能混淆着用,否則一旦混用,如果在後面爲對象的原型對象
        //賦值新對象時,那麼它將會覆蓋掉之前對propotype對象賦值的方法。
        //使用這種方式定義的類
        var a = new CheckObject();
        a.checkName();
        a.checkEmail();
        a.checkPassword();
         //調用了3個方法,但是你對對象a書寫了三遍。這是可以避免的。那就要在你生命的每一個方法
         //末尾處將當前對象返回,在JavaScript中this指向就是當前對象,所以你可以將它返回。例如
         //我們開始寫的第一個對象還記得嗎
         var CheckObject = {
             checkName:function(){
                 //驗證名字
                 return this;
             },
             checkEmail:function(){
                 //驗證郵箱
                 return this
             },
            checkPassword:function(){
                //驗證密碼
                return this
            }
         }
         //此時使用他就可以這樣
         CheckObject.checkName().checkEmail().checkPassword();
         //當然同樣的讓是還可以放到類的原型當中
         var CheckObject = function(){}
         CheckObject.prototype={
             checkName:function(){
                 //驗證姓名
                 return this;
             },
             checkEmail:function(){
                 //驗證郵箱
                 return this;
             },
             checkPassword:function(){
                 return this;
             }
         }
         //但使用時候也要先創建一下
         var a = new CheckObject();
         a.checkName().checkEmail().checkPassword();
         //如果你想給每一個函數都添加一個檢測有限狗的方就可以這樣做
         Function.prototype.checkEmail = function(){
             //驗證郵箱
         }
         //這樣在使用這個方法就方便多了啦,如果你喜歡函數形式
         var f= function(){

         }
         f.checkEmail();
         //如果你習慣類的形式
         var f = new Function();
         f.checkEmail();
         //但是這麼做事不允許的,因爲污染了原生對象Function,所以別人創建的函數也會被你
         //創建的函數所污染,造成不必要的開銷,但是你可以抽象出來一個統一添加方法的功能
         Function.prototype.addMethod = function(name,fn){
             this[name] = fn;
         }
         //這樣如果你想添加郵箱驗證和姓名驗證方法你可以這樣做
         var methods= function(){}
         //或者
         var methods = new Function();
         methods.addMethod('checkName',function(){
             //驗證姓名
         });
         methods.addMethod('checkName',function(){
             //驗證郵箱
         });
         methods.checkEmail();
         methods.checkName();

         //可以鏈式添加嘛
         Function.prototype.addMethod = function(name,fn){
             this[name]=fn;
             return this;
         }

         //如果你在想添加方法就可以這樣了
         var methods = function(){};
         methods.addMethod('checkName',function(){
             //驗證姓名
         }).addMethod('checkEmail',function(){
             //驗證郵箱
         })
         //既然添加方法的時候可以將this返回現實,那麼添加的每個方法將this返回
         var methods = function(){};
         methods.addMethod('checkName',function(){
             //驗證姓名
             return this;
         }).addMethod('checkEmail',function(){
             //驗證郵箱
             return this;
         })
         methods.checkName().checkEmail()

         //可是在你測試的時候,你用的是函數式調用方式?對於習慣於類式調用方式的同學來說
         //他們可以這樣簡單的改一下
         Function.prototype.addMethod = function(name,fn){
             this.prototype[name] = fn;
             return this;
         }
         //此時我們還按照上一種方式添加方法
         var Methods = function(){}
         Methods.addMethod('checkName',function(){
             //驗證姓名
         }).addMethod('checkEmail',function(){
             //驗證郵箱
         })
         var m = new Methods();
         m.checkEmail()


         //2.2包裝明星-封裝
         //2.21創建一個類
         //在js中創建一個類很容易,首先聲明一個函數保存在一個變量裏。按編程習慣將這個代表
         //類的變量名首字母大寫。然後在這個函數(類)的內部通過對this(函數內部自帶的一個變量,
         //用於指向當前這這個對象)變量添加屬性或者方法來實現對類添加屬性或者方法 例如:
         var Book = function(id,bookname,price){
             this.id = id;
             this.bookname = bookname;
             this.price = price;
         }
         //"也可以通過在類圓形(類也是一個對象,所以也有原型prototype)上添加屬性和方法有兩種
         //方式,一種是一一爲原型對象屬性賦值,另一種是將一個對象賦值給類的原型對象,但這
         //兩種不用混用,例如。"
         Book.prototype.display = function(){
             //展示這本書
         };
         //或者
         Book.prototype = {
             display : function(){}
         }
         //這樣我們將所需的方法和屬性都封裝在我們抽象的Book類裏面了,當使用功能方法時,我們
         //不能直接使用這個Book類,需要用new關鍵字來實例化(創建)新的對象。使用實例化的屬性
         //或者方法時,可以通過點語法訪問,例如
         var book = new Book(10,'設計模式',50);
         console.log(book.bookname)//設計模式

         //私有屬性和私有方法,特權方法,對象共有屬性和對象共有方法,構造器
         var Book = function(id,name,price){
             //私有屬性 
             var num = 1;
             //私有方法
             function checkId(){

             }; 
             //特權方法
             this.getName = function(){}
             this.getPrice = function(){}
             this.setName = function(){}
             this.setPrice = function(){}
             //對象公有屬性
             this.copy = function(){}
             //構造器
             this.setName(name);
             this.setPrice(price);
         }

         //類靜態公共有屬性(對象不能訪問)
         Book.isChinese = true;
         //類靜態公有方法(對象不能訪問)
         Book.resetTime = function(){
             console.log('new Tiem')
         };
         Book.prototype = {
             //公有屬性
             isJSBook:false,
             //公有方法
             display:function(){}
         }
         //通過new關鍵字創建的對象實質是對新對象this的不斷賦值,並將prototype指向類的prototype所指向的對象,而類的構造函數外面通過
         //點語法定義的屬性方法是不會添加到新創建的對象上去的。因此要想在新創建的對象中使用inChinese就得通過Book類使用而不能通過this,
         //如Book.inChinese,而類的原型prototype上定義的屬性在新對象裏就可以直接使用,這是因爲新對象的prototype和類似的prototype指向
         //的是同一個對象
         var b = new Book(11,'JavaScript',50); 
         console.log(b.num)                     //undefined
         console.log(b.isJSBook)                //false
         console.log(b.id)                      //11
         console.log(b.inChinese)               //undefined
         //類的私有屬性num以及靜態共有屬性inChinese在新創建的b對象裏是訪問不到的。而類的共有屬性isJSBook在b對象中卻可以通過點語法訪問到
         //但是類的靜態公有屬性inChinese可以通過類的自身訪問
         console.log(Book.inChinese); //true
         Book.resetTime(); //new Tiem
         
         //我們經常將類的靜態變量通過閉包來實現
         var Book = (function(){
             //靜態私有變量
             var bookNum = 0;
             //靜態私有方法
             function checkBook (name){

             }
             return function(newId,newNmae,newPrice) {
                 //私有變量
                 var name,price;
                 //私有方法
                 function checkId(id){}
                 //特權方法
                 this.getName = function(){};
                 this.getPrice = function(){};
                 this.setName = function(){};
                 this.setPrice = function(){};
                 //公有屬性
                 this.id = newId;
                 //公有方法
                 this.copy = function(){};
                 bookNum++
                 if(bookNum > 100)
                    throw new Error('大薩達')
                //構造器
                this.setName(name);
                this.setPrice(price);
             }
         })()
         Book.prototype = {
             //靜態公有屬性
             isJSBook:false,
             //靜態公有方法
             display:function(){}
         }
         
         //閉包是有權訪問另外一個函數作用域中變量的函數,即在一個函數內部創建另外一個函數。我們將這個閉包作爲創建對象的構造函數,這樣
         //它既是閉包又是實例對象的函數,即可訪問到類函數作用域中的變量,如bookNum這個變量,此時這個變量叫靜態私有變量,並且checkBook()
         //可稱爲靜態私有方法。當然閉包內部也有其自身的私有變量以及私有方法如pricce,checkID()。但是,在閉包外部添加言行屬性和方法看上去
         //像是脫離了閉包這個類,所以有時候在閉包內部實現一個完整的類然後將其返回,看下面的例子
         //利用閉包實現
         var Book = (function(){
             //靜態私有變量
             var bookNum = 0;
             //靜態私有方法
             function checkBook(name){

             }
             //創建類
             function book(newId,newName,newPrice){
                 //私有變量
                 var name,price;
                 //私有方法
                 function checkID(id){}
                 //特權方法
                 this.getName = function(){};
                 this.getPrice = function(){};
                 this.setName = function(){};
                 this.setPrice = function(){};
                 //公有屬性
                 this.id = newId;
                 //公有方法
                 this.copy = function(){}
                 bookNum++
                 if(bookNum>100)
                    throw new Error('我們啦啦啦啦啦');
                //構造器
                this.setName(name);
                this.setPrice(price);
             }
             //構造原型
             _book.prototype = {
                 //靜態公有屬性
                 isJSBook:false,
                 //靜態公有方法
                 display:function(){}
             }; 
             //返回類
             return _book;
         })();

         //一般對初學者來說,在創建對象上由於不適應這種寫法,所以經常容易忘記使用new而犯錯誤,如果犯錯誤有人實時監測就解決了
         //所以找一位檢查長,比如JavaScript在創建對象時有一種安全模式就完全可以解決你們這類問題
         //圖書類
         var Book = function(title,time,type){
            this.title = title;
            this.time = time;
            this.type = type;
         }
         //實例化一本書
         var book = Book('JavaScript','2014','js');
         console.log(book);//undefined
         console.log(window.title);//Javescript
         console.log(window.time);//2014
         consoe.log(window.type);//js
         //怎麼樣發現問題了嗎,
         //明明創建了一個Book對象,並添加了title、time、type3個屬性,怎麼會添加到window上面去了,而且book這個變量還是Undefined。
         //因爲沒有new是實例化對象,可是爲什麼會出現這個結果呢
         //首先你要明白一點,new關鍵字的作用可以看做是對當前你對象this不停地賦值,然而例子中沒有用new,所以就會直接直接執行這個函數,
         //而這個函數在全局作用域中執行了,所以在全局作用域中this指向的當前對象自然就是羣居變量,再這個頁面中全局變量就是window了,
         //所以添加的屬性自然就會被添加到window上面了,而我們這個book變量最終的作用是要得到Book變量的執行結果了,所以就是undefind
         //(未定義) 該如何避免呢
         //去找位檢查長 使用安全模式
         //圖書安全類
         var Book = function(title,time,type) {
             //判斷執行過程中this是否是當前這個對象(如果是說明是用new創建的)
             if(this instanceof Book) {
                 this.title = title;
                 this.time = time;
                 this.type = type;
                 //否則重新創建這個對象
             }else {
                 return new Book(title,time,type);
             }
         }
         var book = Book('JavaScript','2014','js');
         //測試
         console.log(book); //Book
         console.log(book.title);//JavaScript
         console.log(book.time);//2014
         console.log(book.type);//js
         console.log(window.title);//undefined
         console.log(window.time);//undefined
         console.log(window.type);//undefined

         //繼承
         //子類的運行對象-類式繼承
         //聲明父類
         function SuperClass(){
             this.SuperClass = true
         }
         //爲父類添加共有方法
         SuperClass.prototype.getSuperValue = function(){
             return this.superValue
         }
         //聲明子類
         function SubClass(){
             this.subValue = false;
         }
         //繼承父類
         SubClass.prototype = new SuperClass();
         //爲子類添加共有方法
         SubClass.prototype.getSubValue = function(){
             return this.subValue
         }
         //繼承混簡單就是聲明2個類而已,不過類式繼承需要將一個誒的實例賦值給第二個類的原型
         //類的原型對象的作用就是爲類的原型添加共有方法,但類不能直接訪問這些屬性和方法,
         //必須通過原型propototype來訪問。而我們實例化一個父類的時候,新創建的對象複製了父類
         //的構造函數內的屬性與方法並且將原型_proto_指向了腹肌的原型對象,這樣就擁有了父。類的原型對象
         //上的屬性與方法,並且這個新創建的對象可直接訪問到父類原型對象上的屬性與方法。如果我們將這個新創建的
         //對象賦值給字類的原型,那麼子類的原型就可以訪問到父類的原型屬性和方法
         //補充一點,上面說的新創建的對象不僅僅可以訪問父類原型上的屬性和方法,同樣也可訪問從父類構造函數中複製的屬性和方法
         //你將這個對象賦值給子類對像的原型,那麼這個子類的原型同樣可以訪問父類原型上的屬性和方法與從父類構造函數中複製的
         //屬性和方法。這正是類式繼承的原理
         //使用子類
         var instance = new SubClass();
         console.log(instance.getSuperValue());//true
         console.log(instance.getSubValue());//false
         //另外還可以通過instanceof來檢測某個對像是否是某個類的實例,或者說某個對像是否繼承了某個類。這樣就可以判斷對像之間的
         //繼承關係了 instanceof是通過判斷對像的prototypr鏈來確定這個對象是否是某個類的實例,而不關心對象與類的自身結構
         //測試代碼
         console.log(instance instanceof SuperClass)
         console.log(instance instanceof SubClass)
         console.log(SubClass instanceof SuperClass)
         //我們說subClass繼承superClass,可是爲什麼SubClass instanceof SuperClass得到的結果是false呢?
         //前面說了,instanceof是判斷前面的兌現是否是後面類(對象)的實例,它並不表示兩者的繼承,這一點不要弄混了,其次
         //我們看看前面的代碼,你看我們在實現subClass繼承SuperClass時是通過將superClass的實例賦值給subClass的原型prototype,
         //所以說SubClass.prototype繼承了superClass
         console.log(SubClass.prototype instanceof SuperClass);//true
         //這種類式繼承還有2個缺點其一,由於子類通過其原型prototype對父類實例化,繼承了父類。隨意說父類中的共有屬性要是引用類型,
         //就會在子類中被所有實例公用,因此一個子類的實例更改子類原型從父類構造函數中繼承來的共有屬性就會直接影響到其他子類,
         //比如你看下面的代碼
         function SuperClass () {
             this.books = ['JavaScript','html','css'];
         }
         function SubClass () {}
         SubClass.prototype = new SuperClass();
         var instance1 = new SubClass();
         var instance2 = new SubClass();
         console.log(instance2.books);//["JavaScript","html","css"]
         instance1.books.push('設計模式');
         console.log(instance2.books);//["JavaScript","html","css","設計模式"]
         //“instance1的一個無意的修改就會無情地傷害了instance2的book屬性,這在編程中很容易埋藏陷阱。其2二,由於子類實現的繼承是靠其
         //原型prototype對父類的實例化實現的,因此在創建父類的時候,是無法向父類傳遞參數的,因而在實例化父類的實例化實現的,因此在
         //創建父類的時候,是無法向父類傳遞參數的,因而在實例化父類的時候也無法對父類構造函數內的屬性進行初始化”
         //那我們該如何解決呢
         //構造函數繼承
         //聲明父類
         function SuperClass (id) {
             //引用類型共有屬性
             this.books = ['JavaScript','html','css'];
             //值類型共有屬性
             this.id = id;
         }
         //父類聲明原型方法
         SuperClass.prototype.showBook = function(){
             console.log(this.books);
         }
         //聲明子類
         function SubClass(id){
             //繼承父類
             SuperClass.call(this,id);
         }
         //創建第一個子類實例
         var instance2 = new SubClass(10);
         //創建第二個子類的實例
         var instance2 = new SubClass(11);
         insyance1.books.push("aaa");
         console.log(instance1.books);//["JavaScript","html","css","aaa"];
         console.log(instance1.id);   //10
         console.log(instance2.books);//["JavaScript","html","css"]
         console.log(instance2.id);  //11
         instance1.books();          //TypeError2
         //注意這裏,SuperClass.call(this,id);這條語句手機構造函數式繼承的精華,由於call這個方法可以更改函數的作用環境,因此
         //在子類中,對superClass調用這個方法就是將子類中的變量在父類中執行一遍,由於父類中是 給this綁定屬性的,因此子類自然也就
         //繼承了父類的共有屬性。由於這種類型的繼承沒有涉及原型prototype,所以父類的原型方法自然不會被子類繼承,而如果想要被子類
         //繼承就必須要放在構造函數中,這樣創建出來的每個實例都會單獨擁有一份而不能公用,這樣就違背了代碼複用的原則。爲了綜合這
         //兩種模式的有點,後來又了組合繼承
         //組合繼承
         //組合繼承是不是說將這兩種繼承模式綜合到一起呀?那麼它又是如何做到的你?
         //我們先總結一下之前兩種模式的特點,類式繼承是通過子類的原型prototype對父類實例化來實現的,構造函數式繼承是通過在子類的構造函數
         //作用環境中執行一次父類的構造函數來實現的,所以只要在繼承中同時做到這兩點即可,
         //組合繼承
         //聲明父類
         function SuperClass (name) {
             //值類型共有屬性
             this.books = ["html","css","JavaScript"];
         }
         //父類原型共有方法
         SuperClass.prototype.getName = function(){
             console.log(this.name);
         };
         //聲明子類
         function SubClass(name,time){
             //構造函數式繼承父類name屬性
             SuperClass.call.call(this,name);
             //子類中新增共有屬性
             this.time = time;
         }
         //類式繼承 子類原型繼承父類
         SubClass.prototype = new SuperClass();
         //子類原型方法
         SubClass.prototypr.getTime = function(){
             console.log(this.time);
         }
         //在子類構造函數中執行父類構造函數,在子類的原型上實例化父類就是組合模式,在這樣就融合了類式繼承和構造函數繼承的有點,
         //並且過濾掉其缺點,測試看看
         var instance1 = new SubClass("js book",2014);
         instance1.books.push("設計模式");
         console.log(instance1.books);//["html","css","JavaScript","設計模式"]
         instancal.getName();//js book
         instance1.getTime();//2014

         var instance2 = new SubClass("css book",2013);
         console.log(instance2.books);//["html","css","JavaScript"]
         instance2.getName();         //css book
         instance2.getTime();         //2013
         //子類的實例中更改父類繼承下來的引用類型屬性如books,根本不會影響到其他實例,並且子類實例比例化過程中又能將參數傳遞到父類的
         //構造函數中,如name。這種模式真的很強大,所以這應該是繼承中最完美的版本吧
         //還不是,因爲我們在使用構造函數。因此父類構造函數調用了兩遍,所以這還不是最完美的方式。
         //原型式繼承
         //2006年道格拉斯.克羅克福德發表一篇《JavaScript 中原型式繼承》的文章,他的觀點是,藉助原型prototype可以根據已有的
         //對象創建一個新的對象,同時不必創建新的自定義對象類型。大師的話理解起來可能很困難,不過我們還是現看一下他實現的代碼吧
         //原型是繼承
         function inheritObject(o){
             //聲明一個過渡函數對象
             function F(){}ttyyyyyyyyy
         }
    </script>
</body>
</html>
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章