0728 NOTE

0728 NOTE

1.setter和getter

  • getter 是一种获得属性值的方法,setter是一种设置属性值的方法
  • getter负责查询值,它不带任何参数,setter则负责设置键值,值是以参数的形式传递,在他的函数体中,一切的return都是无效的
  • get/set访问器不是对象的属性,而是属性的特性,特性只有内部才用,因此在javaScript中不能直接访问他们,为了表示特性是内部值用两队中括号括起来表示如[[Value]]
  • 对象的属性又可分为对象属性和访问器属性
  • set与get相比于属性本身,执行速度较慢,因此需要时再调用
//var obj = {
//            a: 1,
//            b: function () {
//                return 3;
//            }
//        }

        // 属性通过等号赋值,方法不可以,属性具备存储值的能力,方法不能存储值,
        // 属性可以获取值,方法可以返回值,属性只能存储一个值,方法可以传入多个参数
        // 属性存储值时,仅存储,方法执行虽不能存值,但是可以执行多个语句块
        // obj.a=10;
        // var a=obj.b(1,2,3);
        // console.log(obj.a);


        // 处理一个介于属性和方法之间方式,就是为了可以存值的同时,可以执行多个语句块



        //   var divs=document.querySelectorAll("div");
        // var a;
        //   setNum(2);
        //   console.log(a);



        //   function setNum(n){
        //       a=n;
        //     for(var i=0;i<divs.length;i++){
        //         divs[i].textContent=n+i;
        //     }
        //   }





        // var obj = {
        //     _a: 0,
        //     set a(value) {
        //         this._a = value
        //         var divs = document.querySelectorAll("div");
        //         for (var i = 0; i < divs.length; i++) {
        //             divs[i].textContent = value + i;
        //         }
        //     },
        //     get a() {
        //         return this._a;
        //     }
        // }

        // obj.a=10;
        // obj.a=20;
        // console.log(obj.a);
        // console.log(obj.a);
        // obj.a()  不存在

        // obj.a=obj.a+2;

        // setInterval(function(){
        //     obj.a++;
        // },200)


        // 注入式
        // 特征:注入数据,改变显示内容,数据驱动显示,一般用于父元素注入数据给子元素,驱动子元素内容显示改变


        // var obj = {
        //     _a: 0,
        //     // set a(value) {
        //     //     this._a = value
        //     //     var divs = document.querySelectorAll("div");
        //     //     for (var i = 0; i < divs.length; i++) {
        //     //         divs[i].textContent = value + i;
        //     //     }
        //     // },
        //     get a() {
        //         return this._a;
        //     }
        // }

        // 仅设置了set,没有设置get,这种情况就是仅能设置,不能获取
        // 仅设置了get ,没有设置set,这种情况就是仅能读取,不能设置  ,只读

        // console.log(obj.a);




        // 写法种类

        // 新创建对象设置set和get
        //  var obj = {
        //     _a: 0,
        //     set a(value) {
        //         this._a = value
        //     },
        //     get a() {
        //         return this._a;
        //     }
        // }

        // 针对已有对象
        // var div=document.querySelector("div");
        // Object.defineProperties(div,{
        //     _width:{writable:true,value:0},
        //     _height:{writable:true,value:0},
        //     _bg:{writable:true,value:"rgba(0,0,0,0)"},
        //     width:{
        //         set:function(value){
        //             this._width=value;
        //             this.style.width=value+"px";
        //         },
        //         get:function(){
        //             return this._width;
        //         }
        //     },
        //     height:{
        //         set:function(value){
        //             this._height=value;
        //             this.style.height=value+"px";
        //         },
        //         get:function(){
        //             return this._height;
        //         }
        //     },
        //     bg:{
        //         set:function(value){
        //             this._bg=value;
        //             this.style.backgroundColor=value;
        //         },
        //         get:function(){
        //             return this._bg;
        //         }
        //     }
        // })

        // div.width=50;
        // div.height=50;
        // div.bg="red";
        // div.width=1;
        // div.height=30;
        // div.bg="red";

        // setInterval(function(){
        //     div.width++;
        // },16);




        // ES6面向对象

        // class Box{
        //     _num=0;
        //     constructor(){

        //     }
        //     set num(value){
        //         this._num=value;
        //     }
        //     get num(){
        //         return this._num;
        //     }
        //     // 常量
        //     get EVENT_ID(){
        //         return "Event_ID";
        //     }
        // }


        // var b=new Box();
        // b.num=10;
        // console.log(b.num);
        // b.EVENT_ID=12;
        // console.log(b.EVENT_ID);

2.闭包

闭包 是指内部函数总是可以访问其所在的外部函数中声明的变量和参数,即使在其外部函数被返回(寿命终结)了之后。在某些编程语言中,这是不可能的,或者应该以特殊的方式编写函数来实现。但是如上所述,在 JavaScript 中,所有函数都是天生闭包的,但是使用 new Function 创建一个函数,那么该函数的[[Environment]] 并不指向当前的词法环境,而是指向全局环境。因此,此类函数无法访问外部(outer)变量,只能访问全局变量。

​ 通常,函数调用完成后,会将词法环境和其中的所有变量从内存中删除。因为现在没有任何对它们的引用了。与 JavaScript 中的任何其他对象一样,词法环境仅在可达时才会被保留在内存中。但是,如果有一个嵌套的函数在函数结束后仍可达,则它将具有引用词法环境的 [[Environment]] 属性。

​ 当词法环境对象变得不可达时,它就会死去(就像其他任何对象一样)。换句话说,它仅在至少有一个嵌套函数引用它时才存在。

闭包特点

  1. 作用域空间不销毁

    • 优点: 因为不销毁,变量页不会销毁,增加了变量的生命周期
    • 缺点: 因为不销毁,会一直占用内存,多了以后就会导致内存溢出
  2. 可以利用闭包访问再一个函数外部访问函数内部的变量

    • 优点: 可以再函数外部访问内部数据
    • 缺点: 必须要时刻保持引用,导致函数执行栈不被销毁
  3. 保护私有变量

    • 优点: 可以把一些变量放在函数里面,不会污染全局
    • 缺点: 要利用闭包函数才能访问,不是很方便
     //     function fn(){
        //         var a=1;
        //         return function(){
        //             a++;
        //             console.log(a);
        //         }
        //     }
    
        //     var f=fn();
        //     f();
    
    
        //    var utils=(function(){
        //        var a=1;
        //         return {
        //             init:function(){
        //                 a++;
        //                 console.log(c);
        //             }
        //         }
        //     })();
    
        //     utils.init();
    
    
        // var div=document.querySelector("div");
        // div.οnmοusedοwn=function(e){
        //     document.οnmοusemοve=function(e1){
        //         div.style.left=e1.clientX-e.offsetX+"px";
        //         div.style.top=e1.clientY-e.offsetY+"px";
        //     }
        //     document.οnmοuseleave=function(){
        //         document.οnmοusemοve=null;
        //         document.οnmοuseleave=null;
        //         document.οnmοuseup=null;
        //     }
        //     document.οnmοuseup=function(){
        //         document.οnmοusemοve=null;
        //         document.οnmοuseleave=null;
        //         document.οnmοuseup=null;
        //     }
        // }
    
        // 会造成内存泄漏,所有的闭包都会造成内存泄漏
        // 优点 会产生私有变量,减少变量污染
    
    
    //     function bind(fn,obj){
    //         return function(){
    //             fn.apply(obj,arguments)
    //         }
    //     }
    
    
    //     function fns(_a,_b){
    //         this.a=_a;
    //         this.b=_b;
    //         console.log(this.a+this.b);
    //     }
    
    
    //     var obj={a:1,b:2};
    
    //    var f=bind(fns,obj);
    
    //    f(3,5);
    

3.函数柯里化

柯里化(Currying)是一种关于函数的高阶技术。它不仅被用于 JavaScript,还被用于其他编程语言。

柯里化是一种函数的转换,它是指将一个函数从可调用的 f(a, b, c) 转换为可调用的 f(a)(b)(c)

柯里化不会调用函数。它只是对函数进行转换。

// function curry(){
        //     var arr=[];
        //     return function(){
        //         arr=[].concat(arguments);
        //         console.log(arr);
        //         console.dir(arguments);
        //         return arr;
                // arr=[].concat.apply(arr,arguments);
            //    if(arguments.length>0){
            //     [].push.apply(arr,arguments)
            //    }else{
            //        return arr.reduce((value,item)=>value+item);
            //    }

        //     }
        // }



        // function getSum(){

        // }


        // getSum(1);
        // getSum(2,3);
        // getSum(4,5,6);
        // getSum(7,8,9,10);
        // var sum=getSum();
        // console.log(sum);


        // var fn=curry();
        // fn(1,2,3)
        // fn(4,5,6)
        // var s=fn();
        // console.log(s);





        // function currying(fn){
        //     var arr=[];
        //     return function (){
        //         if(arguments.length>0){
        //             [].push.apply(arr,arguments);
        //             return arguments.callee;
        //         }else{
        //         //    return  fn.apply(null,arr);
        //             return fn(...arr);
        //         }
        //     }
        // }


        // var f=currying(function(){
        //     return [].reduce.call(arguments,(value,item)=>value+item);
            //    return [].reduce.apply(arguments,[(value,item)=>value+item])
        // })
        // var f=currying((...arg)=>{
        //     return arg.reduce((value,item)=>value+item);
        // })


        // f(1,2,3);
        // f(4,5,6);
        // f(8,9);
        // var s=f();
        // console.log(s);


        // var s=f(3,4,5)(2,1)(6,7)();
        // console.log(s);

        // function fn(a,b,c,d){
        //    var s=[].reduce.call(arguments,function(value,item){
        //         return value+item;
        //     },0);
        //     console.log(s);
        // }

        // fn(1,2,3,4);

4.原型

函数有原型,对象有原型链

  • 在 JavaScript 中,对象有一个特殊的隐藏属性 [[Prototype]](如规范中所命名的),它要么为 null,要么就是对另一个对象的引用。该对象被称为“原型”。

  • 当从 object 中读取一个缺失的属性时,JavaScript 会自动从原型中获取该属性。在编程中,这种行为被称为“原型继承”。

  • __proto__ [[Prototype]] 的因历史原因而留下来的 getter/setter

  • __proto__ 属性有点过时了。它的存在是出于历史的原因,现代编程语言建议我们应该使用函数 Object.getPrototypeOf/Object.setPrototypeOf 来取代 __proto__ 去 get/set 原型。

    • __proto__ 被认为是过时且不推荐使用的(deprecated),这里的不推荐使用是指 JavaScript 规范中规定,proto 必须仅在浏览器环境下才能得到支持。

      现代的方法有:

      应该使用这些方法来代替 __proto__

  • 原型仅用于读取属性。对于写入/删除操作可以直接在对象上进行。

  • 无论在哪里找到方法:在一个对象还是在原型中。在一个方法调用中,this 始终是点符号 . 前面的对象。

  • for..in 循环也会迭代继承的属性。(如果想排除继承的属性,那么通过内建方法 obj.hasOwnProperty(key):如果 obj 具有自己的非继承的 属性,则返回 true。)

  • 按照规范,所有的内建原型顶端都是 Object.prototype。这就是为什么有人说“一切都从对象继承而来”。

  • 如果 F.prototype 是一个对象,那么 new 操作符会使用它为新对象设置 [[Prototype]]。(注意,这里的 F.prototype 指的是 F 的一个名为 "prototype" 的常规属性。每个函数都有 "prototype" 属性,默认属性)

  • 默认的 "prototype" 是一个只有属性 constructor 的对象,属性 constructor 指向函数自身。

  • 默认情况下,所有函数都有 F.prototype = {constructor:F},所以可以通过访问它的 "constructor" 属性来获取一个对象的构造器。

// function fn(){

        // }

        // 通常直接执行函数,原型没有什么作用,当函数作为构造函数使用时,原型就有意义了
        // fn.prototype

        // fn();
        // fn.call();
        // fn.apply();

        // new 函数这种写法,叫做实例化,被new的函数叫做构造函数,js中构造函数和类名相同
        // var a=new fn();
        // console.log(a);





        // ES5 

        // function Box(n){
        //     // console.log(n);
        // }

        // var b=new Box(5);
        // console.log(b.constructor===Box);


        // ES6

        // class Box{
        //     constructor(n){
        //         console.log(n);
        //     }
        // }

        // var c=new Box(5);
        // console.log(c.constructor===Box);


        // ES5

            // Box就是构造函数
        function Box(){
            // console.log(this);
        }
        // console.log(Box.prototype);
        // Box.prototype.a=1;
        // Box.prototype.b=function(){
        //     console.log("aa");
        // }

        // Box.prototype={
        //     constructor:Box,
        //     a:1,
        //     b:function(){

        //     }
        // }

        // Object.assign(Box.prototype,{
        //     a:1,
        //     b:function(){
        //         console.log("aaa");
        //     }
        // })

        // Box();
        // 实例化构造函数
        // 构造函数的原型被执行实例化时放入了实例化对象的原型链中
        // var b=new Box();
        // console.log(b.__proto__===Box.prototype);
        // console.log(b);




        // ES6

        class Box1{
            a=0;
            static b=10;
            constructor(a){
                this.a=a;
            }
            play(){
                console.log("aaaa");
            }
            static run(){
                console.log("bbb");
            }
        }

        // Box.b
        // Box.run()
        var a=new Box1(5);
        console.log(a);

        console.log(Box1.b);
        Box1.run();



        // ES5 


        // function Box(a){
        //     this.a=a;
        // }

        // Box.prototype.a=0;
        // Box.prototype.play=function(){
        //     console.log("aaaa");
        // }

        // Object.defineProperty(Box.prototype,"play",{
        //     value:function play(){
        //         console.log("aaaa");
        //     }
        // })

        // Box.b=10;
        // Box.run=function(){
        //     console.log("bbb");
        // }


        // Box.run();
        // console.log(Box.b);

        // var b=new Box(5);
        // console.log(b);

        // console.log(Box.b);
        // Box.run()



        Array.prototype.a=function(){
            // console.log("aaa");
            console.log(this);
        }


        var arr=[1,2,3];
        arr.a();

5.原型重构

Array.prototype.slice_1 = function (start, end) {
            if (start === undefined) start = 0;
            if (end === undefined) end = this.length;
            if (start < 0) start = this.length + start;
            if (start < 0) start = 0;
            if (start > this.length) start = this.length;
            if (end < 0) end = this.length + end;
            if (end < 0) end = 0;
            if (end > this.length) end = this.length;
            var arr1 = [];
            for (var i = start; i < end; i++) {
                arr1[arr1.length] = this[i];
            }
            return arr1;
        }


    //     var arr=[1,2,3,4,5,6];

    //    var arr1=arr.slice_1(3,5);
    //    console.log(arr1);
        


    //    Array.prototype.reduce_1=function(fn,initValue,thisArg){
    //        if(this.length===0)  throw new Error("Reduce of empty array with no initial value");
    //         var index=0;
    //        if(initValue===undefined){
    //             initValue=this[0];
    //             index=1;
    //         }
    //         for(;index<this.length;index++){
    //              if(index in this) initValue=fn.call(thisArg,initValue,this[index],index,this);
    //         }
    //         return initValue;
    //    }

    //    var arr=[1,2,3];
    //     var obj={};
    //    var s= arr.reduce_1(function(value,item){
    //         value+=item
    //         this[item]=value;
    //         return value
    //     },100,obj)
    //     console.log(s,obj);

        // arr.forEach()
        // arr.map()
        // arr.some()
        // arr.every()
        // arr.filter()
        // arr.flatMap()

    //    var arr1=arr.map(function(item){
    //          this[item]=item+10;
    //         return item+10;
    //    },obj);
    //    console.log(arr1,obj);



    // div.rect(50,50,"red");

    // HTMLElement.prototype.rect=function(w,h,bg){
    //     Object.assign(this.style,{
    //         width:isNaN(w) ? w : w+"px",
    //         height:isNaN(h) ? h : h+"px",
    //         backgroundColor:bg
    //     })
    // }

    // var div=document.querySelector("div");
    // div.rect(50,50,"Red")

    // var p=document.querySelector("p");
    // p.rect(100,100,"orange")



        // function fn(){

        // }

        // var f=fn.bind({a:1});


        Function.prototype.bind_1=function(thisArg){
            // this 因为是原型方法,所以this被实例化的对象,谁调用bind_1,this就是谁
            // console.log(this);
            var f=this;
            return function (){
                    // this 因为回调函数执行,所以是window
                    // console.log(this);
                  f.apply(thisArg,arguments);
            }
        }

        // function fns(a,b){
        //     this.a=a;
        //     this.b=b;
        //     this.s=a+b;
        // }

        // var o={}
        // var f=fns.bind_1(o)
        // f(3,5);
        // console.log(o);


        // var obj={
        //     init:function(){
        //         document.addEventListener("click",this.clickhandler.bind_1(this));
        //     },
        //     clickhandler:function(e){
        //         console.log(this);
        //     }
        // }

        // obj.init()




        // function fn1(f){
        //     f();
        // }

        // function fn2(){

        // }
        // fn1(fn2);



       
    //     Function.prototype.curry=function(thisArg=null){
    //         var f=this;
    //         var arr=[];
    //         return function(){
    //             if(arguments.length>0){
    //                 [].push.apply(arr,arguments);
    //                 return arguments.callee;
    //             }else{
    //                 return f.apply(thisArg,arr);
    //             }
    //         }
    //     }


    //     function getSum(...arg){
    //         return arg.reduce((value,item)=>{
    //           if(!this.includes(item)) value+=item;
    //            return value;
    //         });
    //     }


    //    var arr=[3,5,7]
    //    var f=getSum.curry(arr);
    //    f(1,2,3);
    //    f(4,5);
    //    var s=f();
    //    console.log(s);



    //    Object.defineProperties(Array.prototype,{

    //        length1:{
    //            set:function(v){
    //                v=Number(v);
    //                if(isNaN(v))  throw new Error("Error Length,must is Number");
    //                Object.defineProperty(this,"_length1",{value:v,writable:true})
    //                if(v<this.length){
    //                     for(;v<this.length;v++){
    //                         this.pop();
    //                 }
    //                }else{
    //                    for(var len=v-this.length,i=0;i<len;i++){
    //                        this.push(undefined);
    //                    }
    //                }
    //            },
    //            get:function(){
    //               return this._length1;
    //            }
    //        }
    //    })

    // var arr=[1,2,3,4];
    // arr.length1=10;
    // console.log(arr);


    // var div=document.querySelector("div");
    // console.dir(div);

6.proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

const p = new Proxy(target, handler)

/*
target
要使用 Proxy 包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
handler
一个通常以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。
*/

术语

handler

包含捕捉器(trap)的占位符对象,可译为处理器对象。

traps

提供属性访问的方法。这类似于操作系统中捕获器的概念。

target

被 Proxy 代理虚拟化的对象。它常被作为代理的存储后端。根据目标验证关于对象不可扩展性或不可配置属性的不变量(保持不变的语义)。

在不改变原对象的基础上实现对该对象的扩充

详解

 // var obj={a:21}
        // var obj1=new Proxy(obj,{
        //     get:function(target,p){
        //         console.log(target,p);
        //         return target[p]+10;
        //     },
        //     set:function(target,p,value){
        //         target[p]=value;
        //     }
        // })

        // console.log(obj1.a);

        // set
        // var div=document.querySelector("div");
        // var o={width:0,height:0,backgroundColor:"red"};
        // var o1=new Proxy(o,{
        //     set:function(target,p,value){
        //         target[p]=value;
        //         if(p==="width" || p==="height") value=isNaN(value) ? value : value+"px";
        //         div.style[p]=value;
        //     }
        // })
        // o1.width=50;
        // o1.height=50;
        // o1.backgroundColor="red";

        // console.log(o);




        // var o={}
        // var p=new Proxy(o,{
        //     set:function(target,prop,value){
        //         if(typeof value!=="number"){
        //             throw new Error("value must is Number");
        //         }
        //         if(!Number.isInteger(value)){
        //             throw new Error("value must is Integer");
        //         }
        //         target[prop]=value;
        //     }
        // })


    //    p.a=3.5
  
    //    console.log(p);


    // construct
    // function Box(a,b,c,d){
    //     console.log(a,b,c,d);
    // }

    // var Ball=new Proxy(Box,{
    //     construct:function(target,argArr,newTarget){
    //         console.log(target,argArr,newTarget);
    //         return new target(...argArr,10);
    //     }
    // })

    // new Ball(1,2,3);
    // new Box(1,2,3)
       


    // has

    // var o1={abc:10};
    // var obj={a:1,b:2,c:3,d:4,e:undefined};
    // Object.setPrototypeOf(obj,o1);
    // console.log(obj);
    // var o=new Proxy(obj,{
    //     has:function(target,p){
    //         return target.hasOwnProperty(p) && (p in target)
    //     }
    // })

    // console.log("a" in o);



    // apply
    function fn(a,b){
        console.log(a,b,this);
    }

    var div=document.querySelector("div");
    var f=new Proxy(fn,{
        apply:function(target,thisArg,argArr){
            // console.log(target,thisArg,argArr);
            target.apply(div,argArr);
        }
    })


    // f.apply(null,[1,2,3]);
    // f(1,2,3)
    // f.call(null,1,2,3)

    // f(3,5)
    // f.call({a:1},3,5)
    // f.apply({a:1},[3,5])


    f(3,5);
    f.call({a:1},3,5)


    var arr=[1,2,3];
    var arr1=arr.slice(0,2);


//     var divs=document.querySelectorAll("div");
//    var divlist=[].slice.call(divs,0,2);
//    var  slice=[].slice.uncurry();
//    var divslist=slice(divs,0,2)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

菜鸟小胖砸

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值