js高级(代理,浅拷贝深拷贝,节流和防抖,闭包.hasOwnProperty)

1.代理

1.问题:如何定义一个对象,不会被修改,也不能被遍历?
  1. 通过Object.defineProperty(对象,属性名,option)定义默认属性

    • 无法被修改
    • 无法被删除
    • 无法被遍历

    注意:Object.Property传入的值与返回的值是同一个地址

  2. 可以配置一下属性

    • value:初始值
    • writable:true (true允许被修改)
    • enumerable:true(rue允许被遍历)
    • configurable:true(rue允许被删除)
  3. 提供get和set2个方法

    • 注意:get和set不能和value,writable一起使用,当给对象设置属性的值,会触发set
        //    var obj={}
        var o = Object.defineProperty({}, "name", {
            value: "刘德华",//初始值
            writable: true,//true 允许被修改
            enumerable: true,//true 允许被遍历
            configurable: true//true 允许被删除

        })
        //    delete o.name//删除
        // o.name="小易"//修改
        // for(let k in o){
        //     console.log(k,o[k]);//name 刘德华
        // }//遍历
        console.log(o);//{name: '刘德华'}
          var person = {
            name: "吴彦祖",
        }
        //给一个初始值
        person.age = 0
        // 问题:直接操作Person,给Person添加属性,容易出现值的不准确
        // 聘请一个代理(秘书)
        var proxy = Object.defineProperty({}, "age", {
            set(val) {
                if (!(val >= 18 && val <= 50)) {
                    console.log("值不合法");
                } else {
                    console.log("值合法");
                    person.age = val
                }
            },
            get() {
                return `年龄${person.age}`
            }
        })
        // 读写都要经过代理
        proxy.age = 22//设置年龄
        console.log(proxy.age);//读取年龄
        console.log(person);
2.查看方法有几个参数

使用arguments

3.hasOwnProperty
  1. 数组是特殊的对象,也就拥有对象的原型的属性和方法

  2. for…in会遍历原型上的属性和方法

    解决:

    • 使用Object.prototype.hasOwnProperty如果是原型上属性和方法,就为false,不是为true
  3. for…of 不会遍历原型上的属性和方法

    解决:

    • 使用Object.keys结合for…of
Object.prototype.address = "中国"
        function Person(name, age, sex) {
            this.name = name,
                this.age = age,
                this.sex = sex
        }
        var p = new Person("小易", 22, "女")
        // for..in会遍历到父的原型上的属性和方法
        for (let key in p) {
            console.log(key);//name, age, sex,address
        }
        // 解决方案1:使用Object.keys结合for..of
        var keys = Object.keys(p)
        for (let key of keys) {
            console.log(key);//name, age, sex
        }
        // 解决方案2:Object.prototype.hasOwnProperty如果是原型上属性和方法,就为false,不是为true
        for (let key in p) {
            // 如果是原型上属性和方法,就为false,不是为true
            console.log(key,Object.prototype.hasOwnProperty.call(p, key));
            if (Object.prototype.hasOwnProperty.call(p, key)) {
                const el = p[key]
                console.log(el);
               
            }
        }
4.浅拷贝

1.概念:除了第一层地址不共享,第二层以上的地址都共享,就是浅拷贝

2.对象的拷贝方法

  1. Object.assign()
  2. {…obj}

3.数组的浅拷贝

  1. […arr]
  2. arr.slice(0)
  3. [].concat(arr)
  4. arr.filter((item)=>item)
  5. _.clone(arr) lodash的方法
 var Person = {
            name: "老刘",
            age: 50,
            children: {
                name: "小刘",
                age: 20
            }
        }
        // 对象浅拷贝
        // 方法1 
        // var newPerson=Object.assign({},Person)
        // 方法二
        var newPerson = { ...Person }
        Person.name = "老老刘"
        Person.children.name = "小小刘"
        console.log(Person);
        console.log(newPerson);
        console.log(newPerson === Person);//false
        console.log(newPerson.children === Person.children);//true

        // 数组浅拷贝
        var arr = ["00", ["11", 22], { id: 1, name: "aa" }, { id: 2, name: "bb" }]
        // var arr1=[...arr]
        // var arr1=arr.slice(0)
        // var arr1=[].concat(arr)
        var arr1 = arr.filter(function(item){
            return item
        })

        arr1[0] = "99"
        arr1[1][0] = "zzz"
        console.log(arr1);
        console.log(arr);
   // 使用lodash的clone,实现浅拷贝,数组与对象的浅拷贝
        var arr=[11,[22,33],44]
        var arr1=_.clone(arr)
        arr[1][0]="zzzz"
        arr[0]="aaa"
        console.log(arr);
        console.log(arr1);

        var obj={id:1,name:"刘德华",children:{id:2,name:"小小易"}}
        var obj1=_.clone(obj)
        obj.name="zzzz"
        obj.children.name="ffff"
        console.log(obj);
        console.log(obj1);
5.lodash的使用

1复制lodash.js

.https://www.bootcdn.cn/lodash.js/

2.打开官网,查文档

https://www.lodashjs.com/

6.深克隆

1.如何判断引用类型?

1.Object.prototype.toString.call(对象名)

​ 2.constructor.name

2.实现深克隆的方法?

  1. js提供的

    JSON.stringify和JSON.parse能够实现深克隆,但是会丢失方法

  var p=JSON.parse(JSON.stringify(person0))
  1. 自己写

        //------------自己写深克隆---------
            var person0 = {
                id: 1,
                name: "蔡徐坤",
                children: {
                    id: 11,
                    name: "小刘"
                }
            }
            console.log(p);
            function deep(o) {
                let temp;
                if (Object.prototype.toString.call(o).includes("Object")) {
                    temp = {}
                } else if (Object.prototype.toString.call(o).includes("Array")) {
                    temp = []
                }
                for (const key in o) {
                    if (Object.hasOwnProperty.call(o, key)) {
                        // console.log(o[key]);
                        //    如果是引用数据类型,进行递归
                        if (typeof o[key] === "object") {
                            temp[key] = deep(o[key])
                            // console.log(deep(o[key]));
                        } else {
                            // 如果是值类型,直接赋值
                            temp[key] = (o[key])
                        }
    
                    }
                }
                return temp
            }
            var person1 = deep(person0)
            person0.children.name = "jj"
            // console.log(person0);
            // console.log(person1);
    
            /* 
                数组实现深克隆
            */
           var arr0=[11,[22,33],44]
           var arr1=deep(arr0)
           arr0[1][0]="hhh"
           console.log(arr0);
           console.log(arr1);
    
  2. 使用lodash cloneDeep

   var person2 = {
        id: 1,
        name: "蔡徐坤",
        children: {
            id: 11,
            name: "小刘"
        }
    }
    var person3 = _.cloneDeep(person2)
    person2.children.name = "mmmm"
    console.log(person2);
    console.log(person3);
7.闭包

1.概念:

函数嵌套函数,内部函数可以访问外部函数的变量和参数,变量和参数不会被垃圾回收机制所回收

2.闭包的好处

  1. 减少全局变量的污染
  2. 实现缓存

3.形成闭包的3个条件

  1. 函数嵌套函数
  2. 利用作用域(局部/全局)
  3. GC(垃圾回收机制)被使用就不会回收(标记清除法,引用计数法)

4.闭包的优点

  1. 保存变量,让一个变量长期驻扎在内存中,不会被释放’
 //    对于outer来说,a是局部变量
       function outer() {
            var a=100
             //    对于inner来说,a是全局变量
             function inner(){
                a+10
            }
            return inner
       }
       var f=outer()
       console.log(f);
8.节流和防抖

降低执行频率,稀释执行次数

​ 节流 throttle

  // 节流 throttle
       var box = document.querySelector(".box")
        box.onmousemove = throttle(function (e) {
            console.log(e);
            console.log(this);
            console.log(1);
        }, 100)
        // throttle页面加载执行
        function throttle(callback, delay = 600) {
            let start = Date.now()
            return function (e) {
                let end = Date.now()
                if (end - start >= delay) {
                    callback.bind(this)(e)
                    console.log(this);
                    console.log(e);
                    //给start重写标记开始的时间
                    start = end
                }
            }
        }

​ 防抖 debounce

   var box = document.querySelector(".box")
        // 防抖 debounce
        box.onmousemove = debounce(function (e) {
            console.log(e);
            console.log(this);
            console.log(1);
        }, 100)
        function debounce(callback, delay = 600) {
            var timer;
            return function (evt) {
                let self = this
                clearTimeout(timer)
                timer = setTimeout(function () {
                    console.log(this);
                    callback.call(self, evt)
                    // callback.call(self, evt);
                }, delay)
            }
        }

9.盒子拖拽.(原型链+继承+构造函数)

DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }

        .boxRed {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
            top: 115px;
        }

        .boxYellow {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            top: 300px;
        }
    style>
head>

<body>
    <div class="box">div>
    <div class="boxRed">div>
    <div class="boxYellow">div>
    <script>
        // 原型拖拽
        function DragBox(cls) {
            this.el = document.querySelector(cls)
        }
        DragBox.prototype = {
            constructor: DragBox,
            dragStart() {
                let self = this
                this.el.onmousedown = function (e) {
                    let disX = e.offsetX
                    let disY = e.offsetY
                    self.dragIng(disX, disY)
                    self.dragEnd()
                }
            },
            dragIng(x, y) {
                let self = this
                document.onmousemove = function (e) {
                    console.log(this);
                    self.el.style.left = e.pageX - x + "px"
                    self.el.style.top = e.pageY - y + "px"
                }
            },
            dragEnd() {
                document.onmouseup = function () {
                    document.onmousemove = document.onmouseup = null
                }
            },
        }
        new DragBox(".box").dragStart()
        // 红色继承
        function DragBoxLimit(el) {
            DragBox.call(this, el)
        }
        DragBoxLimit.prototype = new DragBox;
        DragBoxLimit.prototype.dragIng = function (x, y) {
            let self = this;
            document.onmousemove = function (e) {
                let mX = e.pageX - x
                let mY = e.pageY - y
                if (mX < 0) {
                    mX = 0
                }
                if (mY < 0) {
                    mY = 0
                }
                self.el.style.left = mX + "px"
                self.el.style.top = mY + "px"
            }
        }
        new DragBoxLimit(".boxRed").dragStart()
        // 黄色继承
        function DragBoxLimitText(el) {
            DragBox.call(this, el)
        }
        DragBoxLimitText.prototype = new DragBox;
        DragBoxLimitText.prototype.dragIng = function (x, y) {
            let self = this;
            document.onmousemove = function (e) {
                let mX = e.pageX - x
                let mY = e.pageY - y
                if (mX < 0) {
                    mX = 0
                }
                if (mY < 0) {
                    mY = 0
                }
                self.el.style.left = mX + "px"
               
                self.el.style.top = mY + "px"
                self.el.innerHTML = "top:" + self.el.style.top + "
left:"
+ self.el.style.left } } new DragBoxLimitText(".boxYellow").dragStart()
script> body> html>

10.盒子拖拽(类)


DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Documenttitle>
    <style>
        .box {
            width: 100px;
            height: 100px;
            background-color: pink;
            position: absolute;
        }

        .boxRed {
            width: 100px;
            height: 100px;
            background-color: red;
            position: absolute;
            top: 115px;
        }

        .boxYellow {
            width: 100px;
            height: 100px;
            background-color: yellow;
            position: absolute;
            top: 300px;
        }
    style>
head>

<body>
    <div class="box">div>
    <div class="boxRed">div>
    <div class="boxYellow">div>
    <script>
        class box {
            constructor(el) {
                this.el = document.querySelector(el)
            }
            dragStart() {
                let self = this
                this.el.onmousedown = function (e) {
                    let disX = e.pageX-this.el.offsetLeft
                    let disY = e.offsetY
                    self.dragIng(disX, disY)
                    self.dragEnd()
                }
            }
            dragIng(x, y) {
                let self = this
                document.onmousemove = function (e) {
                    console.log(this);
                    self.el.style.left = e.pageX - x + "px"
                    self.el.style.top = e.pageY - y + "px"
                }
            }
            dragEnd() {
                document.onmouseup = function () {
                    document.onmousemove = document.onmouseup = null
                }
            }
        }
        class yellowBox extends box {
            constructor(el) {
                super(el)
                // this.left=e.pageX-e.offsetX
            }
            dragIng(x, y) {
                let self = this
                document.onmousemove = function (e) {
                    console.log(this);
                    self.el.style.left = e.pageX - x + "px"
                    self.el.innerHTML = "left:" + self.el.style.left
                    self.el.style.top = e.pageY - y + "px"
                    self.el.innerHTML = "top:" + self.el.style.top + "
left:"
+ self.el.style.left console.log( self.el.style.left); } } } class RedBox extends box { constructor(el) { super(el) // this.left=e.pageX-e.offsetX } dragIng(x, y) { let self = this document.onmousemove = function (e) { console.log(this); let mX = e.pageX - x let mY = e.pageY - y if (mX < 0) { mX = 0 } if (mY < 0) { mY = 0 } self.el.style.left = mX + "px" self.el.style.top = mY + "px" } } } var b = new yellowBox(".boxYellow") var p = new box(".box") var r=new RedBox(".boxRed") r.dragStart() b.dragStart() p.dragStart()
script> body> html>

11.tab栏切换

js高级(代理,浅拷贝深拷贝,节流和防抖,闭包.hasOwnProperty)_第1张图片

 var Main = document.querySelectorAll(".main")
    for (var i = 0; i < TabItem.length; i++) {
        TabItem[i].onclick = change(i)//change会被执行4次
        // console.log(TabItem[i].onclick);
    }
    function change(n) {
        return function (e) {
            for (var i = 0; i < TabItem.length; i++) {
                TabItem[i].className = "tab-item"
                // 下面的图片
                Main[i].className = "main"
            }
            // e.target.className="tab-item active"
            this.className = "tab-item active"
            console.log(this);
            // 下面的图片
            Main[n].className = "main selected"
        }
    }

你可能感兴趣的:(javascript,前端,开发语言)