美文网首页
闭包、跨域、this指向问题

闭包、跨域、this指向问题

作者: px1012 | 来源:发表于2022-02-14 13:42 被阅读0次
    1.闭包是什么?用let怎么实现闭包?有什么优点和缺点?

    闭包的定义:闭包就是指有权访问另一个函数作用域中变量的函数
    优点:① 能够读取函数内部的变量;②外部函数调用对象后其变量对象本应该被销毁,但闭包的存在使我们仍然可以访问外部函数的变量对象
    缺点:①函数的作用域及其所有变量都会在函数执行结束后被销毁。但是,在创建了一个闭包以后,这个函数的作用域就会一直保存到闭包不存在为止。所以内存消耗很大。
    闭包的缺点就是常驻内存会增大内存使用量,并且使用不当很容易造成内存泄露。②闭包只能取得包含函数中的任何变量的最后一个值。
    应用闭包的主要场合是:设计私有的方法和变量。
    先看一个基本的闭包

    function lazy_sum(arr) {
        var sum = function () {
            return arr.reduce(function (x, y) {
                return x + y;
            });
        }
        return sum;
    }
    var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
    f(); // 15
    

    封装一个私有变量(用JavaScript创建一个计数器)

    function create_counter(initial) {
        var x = initial || 0;
        return {
            inc: function () {
                x += 1;
                return x;
            }
        }
    }
    var c1 = create_counter();
    c1.inc(); // 1
    c1.inc(); // 2
    c1.inc(); // 3
    
    var c2 = create_counter(10);
    c2.inc(); // 11
    c2.inc(); // 12
    c2.inc(); // 13
    

    在返回的对象中,实现了一个闭包,该闭包携带了局部变量x,并且,从外部代码根本无法访问到变量x。换句话说,闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。

    用(function(j){})会产生函数级的作用域。
    而用 let 声明的就是块作用域,和函数级的作用域一样都可以用于形成闭包
    具体看下面的例子:

     var arr=[];
         for(var i=0;i<10;i++){
              arr.push(()=>i)
    }
    console.log(arr[2]())   //10
    
    var arr=[];
         for(let i=0;i<10;i++){
         arr.push(()=>i)
    }
    console.log(arr[2]())   //2
    
    js中本地存储有哪些?有什么不同?

    cookie、localStorage、sessionStorage
    相同点:都保存在浏览器端;
    不同点:
    ①传递方式不同
    cookie数据始终在同源的http请求中携带(即使不需要),即cookie在浏览器和服务器间来回传递。
    sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存。
    ②数据大小不同
    (cookie数据还有路径(path)的概念,可以限制cookie只属于某个路径下。) ​ 存储大小限制也不同,cookie数据不能超过4k,同时因为每次http请求都会携带cookie,所以cookie只适合保存很小的数据,如会话标识。
    sessionStorage和localStorage 虽然也有存储大小的限制,但比cookie大得多,可以达到5M或更大。
    ③数据有效期不同
    sessionStorage:仅在当前浏览器窗口关闭前有效,自然也就不可能持久保持;
    localStorage:始终有效,窗口或浏览器关闭也一直保存,因此用作持久数据;
    cookie只在设置的cookie过期时间之前一直有效,即使窗口或浏览器关闭。
    ④作用域不同
    sessionStorage不在不同的浏览器窗口中共享,即使是同一个页面;
    localStorage 在所有同源窗口中都是共享的;
    cookie也是在所有同源窗口中都是共享的。

    跨域 参考

    1)什么是跨域?
    广义的来说:跨域是指一个域下的文档或脚本试图去请求另一个域下的资源。
    其实我们通常所说的跨域是狭义的,是由浏览器同源策略限制的一类请求场景。
    2)什么是同源策略?
    同源策略/SOP(Same origin policy)是一种约定,由Netscape公司1995年引入浏览器,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,浏览器很容易受到XSS、CSFR等攻击。所谓同源是指"协议+域名+端口"三者相同,即便两个不同的域名指向同一个ip地址,也非同源。
    CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本([XSS]),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。
    跨域解决方案
    1、 通过jsonp跨域

    根据浏览器同源策略,所谓同源就是协议、主机、端口号都相同时成为同源。a 域的js不能直接访问 b域名的信息,但是script 标签的src属性可以跨域引用文件,jsonp是请求之后后台包装好一段json,并且把数据放在一个callback函数,返回一个js文件,动态引入这个文件,下载完成js之后,会去调用这个callback,通过这样访问数据。

    跨域资源共享(CORS)
    普通跨域请求:只服务端设置Access-Control-Allow-Origin即可,前端无须设置,若要带cookie请求:前后端都需要设置。

    2、 document.domain + iframe跨域 3、 location.hash + iframe4、 window.name + iframe跨域 5、 postMessage跨域 6、 跨域资源共享(CORS)7、 nginx代理跨域 8、 nodejs中间件代理跨域 9、 WebSocket协议跨域
    Access-Control-Allow-Credentials 响应头会使浏览器允许在 Ajax 访问时携带 Cookie
    对 XMLHttpRequest 设置其 withCredentials 参数,才能实现携带 Cookie 的目标
    vue中跨域解决方法

    方法1.后台更改header
    header('Access-Control-Allow-Origin:*');//允许所有来源访问
    header('Access-Control-Allow-Method:POST,GET');//允许访问的方式 2.使用http-proxy-middleware 代理解决(项目使用vue-cli脚手架搭建)
    例如请求的url:“http://f.apiplus.cn/bj11x5.json
    1、打开config/index.js,在proxyTable中添写如下代码:
    proxyTable: {
    '/api': { //使用"/api"来代替"http://f.apiplus.c"
    target: 'http://f.apiplus.cn', //源地址
    changeOrigin: true, //改变源
    pathRewrite: {
    '^/api': 'http://f.apiplus.cn' //路径重写
    }
    }
    }
    getData () {
    axios.get('/api/bj11x5.json', function (res) {
    console.log(res)
    })
    通过这中方法去解决跨域,打包部署时还按这种方法会出问题。解决方法如下:
    let serverUrl = '/api/' //本地调试时
    // let serverUrl = 'http://f.apiplus.cn/' //打包部署上线时
    export default {
    dataUrl: serverUrl + 'bj11x5.json'
    }

    3.nginx反向代理

    nginx反向代理接口跨域
    跨域原理: 同源策略是浏览器的安全策略,不是HTTP协议的一部分。服务器端调用HTTP接口只是使用HTTP协议,不会执行JS脚本,不需要同源策略,也就不存在跨越问题。
    实现思路:通过nginx配置一个代理服务器(域名与domain1相同,端口不同)做跳板机,反向代理访问domain2接口,并且可以顺便修改cookie中domain信息,方便当前域cookie写入,实现跨域登录。

    image.png
    postMessage

    用法:postMessage(data,origin)方法接受两个参数
    data: html5规范支持任意基本类型或可复制的对象,但部分浏览器只支持字符串,所以传参时最好用JSON.stringify()序列化。
    origin: 协议+主机+端口号,也可以设置为"*",表示可以传递给任意窗口,如果要指定和当前窗口同源的话设置为"/"。

    this的指向问题 参考
    1、在全局范围内,this指向全局对象(浏览器下指window对象)
    2、对象函数调用时,this指向当前对象
    3、全局函数调用时,应该是指向调用全局函数的对象。
    4、使用new关键字实例化对象时,this指向新创建的对象
    5、当用apply和call上下文调用的时候指向传入的第一个参数
    改变this指向的方法:
    1)使用箭头函数;

    箭头函数没有自己的this, 它的this是继承而来; 默认指向在定义它时所处的对象(宿主对象),而不是执行时的对象, 定义它的时候,可能环境是window; 箭头函数可以方便地让我们在 setTimeout ,setInterval中方便的使用this
    2)在函数内部使用_this=this;
    3)使用apply、call、bind
    4)new实例化一个对象;

    相关文章

      网友评论

          本文标题:闭包、跨域、this指向问题

          本文链接:https://www.haomeiwen.com/subject/qilzjctx.html