[关闭]
@lizlalala 2016-11-20T06:52:28.000000Z 字数 5799 阅读 1024

日常笔记

magazine 前端周刊 奇舞


这边的笔记主要记载自己看周刊或者不错的文章中的一些good points,或者一些需要注意的点,当然里面肯定有楼主自己的理解啦:)

  1. const var let区别

    • let const的作用域更小,为块作用域({}),var为函数作用域。如果是for循环中的let ,如
      1. var x = 0;
      2. for (let i = 0; i < 10; i++) {
      3. x += 10;
      4. //i只在该作用域存在
      5. }
      6. try {
      7. console.log(i);
      8. } catch(e) {
      9. console.log(
      10. 'i does not exist here!'
      11. );
      12. }

    输出为: 'i does not exist here!'

    • const只能在声明时初始化,它表示它所代表的引用(可以认为是指针)是不可变的,所指向的内容实际是可以变的。如

      1. const a = {};
      2. a['b'] = 1;
      3. const b = [];
      4. b.push(1)
    • 三者都会变量提升(hoist),只是var提升时会默认设置初始值 undefined,而let,const不会。
      因此,如果在声明时没有初始化,然后就去访问值的话,var会报出undefined,而let,const会抛出ReferenceError

      1. //类似于介个样子
      2. var a;
      3. console.log("a",a); //undefined
      4. a = 3;
  2. this 总结

    最近写ife的task的时候遇到这么一个问题,

    1. Queue.prototype = {
    2. ...
    3. bubbleSort:function(){
    4. var swap = false,that = this,firstRound = true;
    5. var arr = this.queue,
    6. i = 1,
    7. lastIndexOfNotSortedArr = arr.length-1;
    8. var bubbleSortId = setInterval(_runSort,interval);
    9. function _runSort(){
    10. ...
    11. this.render();
    12. //这边的this实际上是window,而不是new出来的对象
    13. }
    14. }

    记得 你不知道的javascript里面有讲解过,好不容易翻出来一点,回忆一下。

    • a. 全局/function中的this都指向window对象
    • b. 显示调用如 a.func(),或者用构造函数新建对象b = new B()时,里面的this 分别指向a,b
    • c. apply,call,bind指向绑定的对象
    • d. 内部函数中的this指向window 此处就印证了上面的代码中的问题
    1. 还有这样的栗子
    2. function Foo() {
    3. this.value = 42;
    4. this.method = function() {
    5. // this refers to the global object
    6. console.log(this.value); // undefined
    7. console.log(this === window); // true
    8. };
    9. setTimeout(this.method, 500);
    10. }

    ************这是一条栗子分割线start*********************
    除此之外,还有一个栗子需要特别注意,对照着看b,d两条。

    See the Pen this in event by lu (@luchen) on CodePen.

    1. var element = document.getElementById('element');
    2. var user = {
    3. firstname: 'Bob',
    4. greeting: function(){
    5. alert('My name is ' + this.firstname);
    6. }
    7. };
    8. user.greeting(); // attention1: My name is Bob
    9. // Attach user.greeting as a callback
    10. element.addEventListener('click', user.greeting);
    11. // attention2: My name is undefined

    attention1处符合b的规则,而attention2中,则实际上是因为:事件绑定函数时,会以当前元素为作用域执行。
    (虽然楼主最开始以为是把user.greeting函数赋给一个匿名回调函数,function(){} = user.greeting.因此在触发它的时候this其实是丢失了的)。不过测试了下,貌似确实是把this绑在了元素上的。具体看codepen里面this.nodeName。
    关于这个问题的解决方案有两种:

    • 包裹在另一个匿名函数中

      1. element.addEventListener('click', function(){user.greeting()});
    • bind user

      1. element.addEventListener('click', user.greeting.bind(user));
      2. //或者一步到位:
      3. user.greeting = user.greeting.bind(user);
      4. element.addEventListener('click', user.greeting);

    ************这是一条栗子分割线 end*********************

    具体的解决方案有三种:

    • var that = this
    • bind
    • es6箭头函数,实际上也是用的第一种方法(经babel转译后可以看到,里面是没有this的,是沿用的外部的this)
      具体见bi项目开发总结第26条
  3. 中文正则

    1. /\u4E00-\u9FA5/
  4. 跨域总结
    在公司开发的过程中其实也遇到过这个问题,是像另一个服务器post请求,是的,坑有两个,一个是跨域,一个是用jsonp解决跨域后发现要用post =。=。但是当时时间紧迫,后端同学不是很会配置,就粗暴的都用jsonp+get解决了

    • 场景:同源策略,出于防范跨站脚本的攻击,禁止客户端脚本(如 JavaScript)对不同域的服务进行跨站调用。跨站调用主要指,只要网站的

      • 协议名protocol
      • 主机host
      • 端口号port

      这三个中的任意一个不同,网站间的数据请求与传输(ajax请求)便构成了跨域调用。
      而用script标签请求和解析则可以正常运作。

    有一点需要注意的是,跨域请求并非是浏览器限制了发起跨站请求,而是请求可以正常发起,到达服务器端,但是服务器返回的结果会被浏览器拦截。

    更直白一点的解释就是,以钓鱼网站(get服务器数据)为例。ta0bao.com,用户提交信息,那么黑客会发送ajax到taobao.com,然后taobao那边的服务器返回数据,如果没有同源策略的话,这个数据就会被获取到。但是有了同源策略,浏览器那边可以得到这个数据,但是黑客在代码里是得不到的。被浏览器拦截了,就不给你就不给你=。=。

    同源只能限制不被获取数据,但是发送其实是限制不了的。比如获取用户的私密信息。比如xss。黑客可以在用户提交信息(加上现在在a.com下)时发送两个ajax,一个给正常的网站(a.com),一个给自己的服务器(b.com)。这个是米有办法阻拦哒,要不然钓鱼网站也不会辣么猖狂...摊手。
    这实际上也说明了跨域出现的原因及解决方案(用获取script代替ajax请求)

    • 解决方案:JSONP

      JSONP是 JSON 的一种使用模式,可以解决主流浏览器的跨域数据访问问题。其原理是根据 XmlHttpRequest 对象受到同源策略的影响,而 标签元素却不受同源策略影响,可以加载跨域服务器上的脚本,网页可以从其他来源动态产生 JSON 资料。用 JSONP 获取的不是 JSON 数据,而是可以直接运行的 JavaScript 语句。
      json数据被封装在回调函数里,就是所谓的json with padding(json填充)


    我们通常会直接用jquery的jsonp的解决方案,用法如下:

    1. requestDict["update"] = $.ajax({
    2. url: urls.update+encodeURIComponent(JSON.stringify(queriesObj)),
    3. type: "get",
    4. dataType: "jsonp",
    5. jsonp: "callback",
    6. jsonpCallback: "handleServerPolyData",//回调
    7. success: function(serverData) {
    8. },
    9. );
    最终发出的url是这样的
    1. http://bigdata.xiaojukeji.com/hotmap/getHeatmapOverlay?productLine=taxi?callback=handleServerHeatData?
    但实际上它是做了一层封装,会有点误导。返回的实际上还是javascript语句,jquery进行了解析,正确时会调用success,同时把里面的数据存为上面的serverData。让你看起来jsonp跟普通的ajax请求没有任何区别。 实际上如果自己实现的话,应该是这样的: server1 请求页面有一个script标签
    1. <script src = 'http://localhost:3001/jsonServerResponse?jsonp=jsonpCallback'></script>
    或者在代码里手动createElement("script"),然后设置src后append到head中。
    1. //server1请求页面的js代码只有下面的回调
    2. function jsonpCallback(data) {
    3. console.log("jsonpCallback: "+data.name)
    4. }
    1. // server2处理请求
    2. app.get('/jsonServerResponse', function(req, res) {
    3. var cb = req.query.jsonp
    4. console.log(cb)
    5. var data = 'var data = {' + 'name: $("#name").val() + " - server 3001 jsonp process",' + 'id: $("#id").val() + " - server 3001 jsonp process"' + '};'
    6. var debug = 'console.log(data);'
    7. var callback = '$("#submit").click(function() {' + data + cb + '(data);' + debug + '});'
    8. res.send(callback)
    9. res.end()
    10. })
    可以看出,服务端返回的应该是一段立即执行的js代码。
    • 优缺点
      • 优点:解析快+解决跨域。jsonp中,由于数据是被当成原生的javascript,因此解析和原生的一样快,所以数据传输时,时间(下载+解析)中的解析部分几乎为0
      • 缺点(动态脚本注入引起的):
        • 不安全
        • 只能get请求
        • 不能设置请求的头信息,也就不能设缓存。也不可以访问请求的头信息
        • 不能失败处理
        • 需要等到所有数据返回才可以访问

    针对jsonp不能支持post等请求的问题,解决方案是cors(Cross-Origin Resource Sharing)
    主要是服务器对响应头进行了处理

    1. //Access-Control-Allow-Origin
    2. res.header("Access-Control-Allow-Origin", "*");
    3. res.header("Access-Control-Allow-Headers", "X-Requested-With");
    4. res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");

    reference:前端跨域请求原理及实践

    ===2016/11/20更新
    本次更新是针对jsonp不能post的问题。之前我们说了可以用cors,这个楼主还没有试过。楼主这次是用前端代理的方法,本质是本地请求本地服务器,本地服务器去做转发,服务器间的转发是没有跨域这个概念的。因此可以解决,而这种方法下,服务端实际上不需要像cors那样进行变更。(场景是,本地开发需要访问另一个域名下的数据)。
    具体方法是:
    vue-cli中,是使用了http-proxy-middleware的中间件(node-http-proxy)进行处理,如下

    1. proxyTable: {
    2. '/ip/serverInfo': {
    3. target: 'https://cnodejs.org', //origin,域名部分
    4. pathRewrite:{'^/ip/serverInfo': '/api/v1/topics'},
    5. changeOrigin: true
    6. },
    7. },
    • webpack中有专门的配置,其实也是利用的http-proxy-middleware
      1. // In webpack.config.js
      2. {
      3. devServer: {
      4. proxy: {
      5. '/api': {
      6. target: 'https://other-server.example.com',
      7. secure: false
      8. }
      9. }
      10. }
      11. }
  5. 即时搜索

    监听v-model变化,每次变动就取消上一次请求。当超过500ms的时候就发送搜索请求。

    1. watch: {
    2. searchInput(newValue, oldValue){
    3. clearTimeout(timer);
    4. if(newValue.trim() !==oldValue.trim())
    5. timer = setTimeout(this.fetchKeywordList,500);
    6. }
    7. },
  6. cookie.js代码赏析

    1. var value = document.cookie.split(/;\s*/)
    2. .map(opt.autoencode ? opt.decode : function (d) { return d; })
    3. .map(function (part) { return part.split('='); })
    4. .reduce(function (parts, part) {
    5. parts[part[0]] = part[1];
    6. return parts;
    7. }, {})[data];

    demo:

    var arr = [{"id":3,"zh_name":"test"},{"id":5,"zh_name":""lili}]
    结果:Object {3: "test", 5: "lili"}

    1. arr.reduce((prev,cur)=>{
    2. prev[cur["id"]] = cur["zh_name"];
    3. return prev;
    4. },{})
  7. 7.
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注