IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> JavaScript知识库 -> 闭包9.19 -> 正文阅读

[JavaScript知识库]闭包9.19

闭包是什么?

  1. 犀牛书:函数变量可以保存在函数作用域内,从技术角度讲,所有函数都是闭包

    function bar(){
        let n = 0;
    }
    
  2. 高级程序设计:闭包是指有权访问另一个函数作用域中变量的函数(函数没导出)

    function foo(){
        let n = 0;
        function bar(){
           console.log(n)
       };	
       bar();   //bar就是闭包
    }
    foo()
    
  3. 你不造的js: 当函数可以记住并访问所在的词法作用城时,就产生了闭包,即使函数是在当前词法作用域之外执行。

    function  foo(){
        let n = 0;
        return function bar(){   //bar就是闭包
            console.log(n);
        };
    }
    foo()();
    
  4. MDN:一个函数和对其周围状态(词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就叫闭包。也就是说,闭包让你可以在一个内层函数中访问到其外层函数的作用域。在JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

总结 参考常见形式便于理解

  1. 函数的执行,导致函数被定义(被定义的函数可以拿到父函数的变量)

  2. 闭包和函数的定义有关

  3. this和函数的执行方式有关

不是闭包的例子:

function foo(fn){
    let n = 0;
    fun();
}
function text(){
    console.log(n);
}
foo(test);

闭包常见形式:

  1. 函数的返回值是函数

    function foo(){
        let n = function(){
            
        }
        return n;
        //or
        //return function(){};
    }
    
  2. 函数内全局定义函数

    let func;
    function foo(){
        let n = 1;
        func = function(){console.log(n)};
    }
    
  3. 函数参数

    let func = function(fn){
        console.log(fn())
    };
    function foo(){
        let a = 'aaa';
        let n = function(){return a};
        func(n)
    }
    foo();
    //------------------------------------------------------------
    (function(){
        let a = 'aaa';
        let n = function(){return a};
        func(n)
    })()
    
  4. 循环赋值

    function foo(){
        let arr = [];
        for(var i =0; i<10; i++){
            arr[i] = function(){
                console.log(i);   
            }
        }
        return arr;
    }
    let bar = foo();
    bar[0]()    //10
    
    //不用let从零打印:function foo(){    let arr = [];    for(var i =0; i<10; i++){        arr[i] = (function(j){xx            console.log(j);           }    })(i)    return arr;}let bar = foo();bar[0]()    //0
    

this指向

默认全局变量为 window

优先级:new>显示绑定>隐式绑定>默认绑定

function函数

  1. 默认绑定

    独立调用,指向window

    console.log(this===window)   //true
    
  2. 隐式绑定

    谁调用就指向谁

    函数执行才会有this,每个函数都有自己的this,this指向是否相等由函数执行方式决定

    let obj = {    foo : function(){        console.log(this);  //obj                function test(){			console.log(this);        }        test()      //独立调用 指向window                (function(){			console.log(this);  //同上  window        })();                function back(){			console.log(this);        }        return back;    }}let a = obj.foo()  // obj window windowa(); //window  独立调用
    
    // 变量赋值function foo(){	console.log(this);}let obj = {    foo : foo}obj.foo(); //objlet a = obj.foo; //隐式丢失 a(); // window
    
    // 参数赋值// 预编译过程中,实参被赋值为形参,值的浅拷贝的过程function foo(){    console.log(this);}function bar(fn){   	fn();    new fn;  // foo {}}let obj = {	foo : foo}bar(obj.foo);   //window
    
    // api 回调函数中的this 参考api文档let arr = [1,2,3];arr.forEach((item,idx,arr)=>{    console.log(this)  //window});arr.forEach((item,idx,arr)=>{    console.log(this)  //obj},obj);
    
  3. 显示绑定

    call,apply,bind

  4. new绑定

    指向实例化对象

    function obj(){	let this = {};	....................	return this;}
    

    如果构造函数return this之外的东西,生成的对象和this指向:

    function foo(){    this.a = 2;    console.log(this);   //{a:2}    return {    	o : 0    };}let f  = new foo;console.log(f);      // {O:0}
    
    function foo(){    this.a = 2;    console.log(this);   //{a:2}    return 1;}let f  = new foo;console.log(f);     //{a:2}
    
    function foo(){    this.a = 2;    console.log(this);   //{a:2}    return "asd";}let f  = new foo;console.log(f);    //{a:2}
    

箭头函数

本身没有this,不受绑定影响,this指向由外层函数作用域决定

function foo(){    console.log(this);    let test = ()=>{        console.log(this);    }    return test;} let obj1 = {    foo : foo}let obj2 = {    foo : ()=>{        console.log(this);    }}let o = obj1.foo();       // foo{}let p = foo().call(obj);  // windowo();                      // foo{}   默认绑定无效obj1.foo();               // window  隐式绑定无效p();                      // window  显示绑定无效let er = new foo();       // Error   箭头函数不允许作为构造函数

做做题把~~

function foo(s){	this.a = s;}let obj = {};let bar = foo.bind(obj);bar(2);console.log(obj.a);let baz = new bar(3);console.log(obj.a);console.log(baz.a);// 2 2 3
let name = 'window'let obj1 = {    name : '1',    fn1 : function () {        console.log(this.name);    },    fn2 : ()=> console.log(this.name),    fn3 : function(){        return function(){            console.log(this.name);        }    },    fn4 : function(){        return ()=> console.log(this.name);    }}let obj2 = {    name : '2'}obj1.fn1();                    obj1.fn1.call(obj2);obj1.fn2();obj1.fn2.call(obj2);obj1.fn3()();obj1.fn3().call(obj2);obj1.fn3.call(obj2)();obj1.fn4()();obj1.fn4().call(obj2);obj1.fn4.call(obj2)();// 1// 2// window// window// window// 2// window// 1// 1// 2

拷贝

定义

  • 浅拷贝是创建一个新对象,这个对象有着原始对象属性值的一份精确拷贝。如果属性是基本类型,拷贝的就是基本类型的值,如果属性是引用类型,拷贝的就是内存地址,所以如果其中一个对象改变了这个地址,就会影响到另一个对象。

  • 深拷贝是将一个对象从内存中完整的拷贝份出来 ,从堆内存中开辟一 个新的区域存放新对象,且修改新对象不会影响原对象。

区别

  • 赋值:当我们把一个对象赋值给个新的变量时, 赋的其实是该对象的在栈中的地址,而不是堆中的数据。也就是两个对象指向的是同一个存储空间,无论哪个对象发生改变,其实都是改变的存储空间的内容,因此,两个对象是联动的。
  • 浅拷贝:重新在堆中创建内存,拷贝前后对象的基本数据类型互不影响,但拷贝前后对象的引用类型因共享同一块内存,会相互影响
  • 深拷贝:从堆内存中开辟一个新的区域存放新对象, 对对象中的子对象进行递归拷贝,拷贝前后的两个对象互不影响。
  JavaScript知识库 最新文章
ES6的相关知识点
react 函数式组件 & react其他一些总结
Vue基础超详细
前端JS也可以连点成线(Vue中运用 AntVG6)
Vue事件处理的基本使用
Vue后台项目的记录 (一)
前后端分离vue跨域,devServer配置proxy代理
TypeScript
初识vuex
vue项目安装包指令收集
上一篇文章      下一篇文章      查看所有文章
加:2021-09-20 15:42:12  更:2021-09-20 15:43:46 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年12日历 -2024/12/28 12:26:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码
数据统计