前端利用代理解决跨域问题

场景

前端:‘后端朋友,你那接口我访问不了,你设置下那个access-control-follow-origin?’
后端:'不要啦,那样容易会被CSRF攻击的啦,又不是测试服的接口,安全很重要的'

遇到这个问题,后端又不想配合你搞搞jsonp(其实也没必要,还真的浪费时间),肯定就要用 代理啦!

代理分为正向代理跟反向代理

正文

今天要讲的是利用fiddler这个软件实现正向代理。

我们新建一个index.html文件,然后该文件里引用js:

$.ajax({
        url: 'http://vote.sina.com.cn/api/survey/vote_status/240',
        method: "POST",
        data: {
            t: 1520434311162
        },
        success: function (data) {
            console.log(data);
        },
})

这个url是我在新浪首页随便找的,一运行index.html就会提示跨越问题:

XMLHttpRequest cannot load http://vote.sina.com.cn/api/survey/vote_status/240. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

这时候fiddler就出场了,
打开该软件(其实谷歌浏览器也可以设置代理,原理一样,但我没试过。。。)

1.选择AutoResponder选择卡
2.勾上Enable rules
3.勾上Unmatched requests passthrough
4.填上 http://www.sina.com.cn
5.填上 index.html的路径(注意是文件路径,跟浏览器里路径的最大区别是‘/’跟‘\’)
6.点击有点的save按钮
好了,现在浏览器里输入http://www.sina.com.cn ,咋们不会跳到新浪首页,而会访问你那个index.html文件,然后在操作台可以看得请求的到数据了。

反向代理下次再聊,我知道webpack里可轻松设置,利用express服务端请求接口不存在跨域这个原理。
如果理解有误,欢迎指正。~

参考文章:
前端开发如何独立解决跨域问题
如何使用Fiddler实现跨域访问(把自己做的静态HTML页面域名变成api.bing.com)

kmp算法

一如既往,推荐看客先看阮一峰博客:字符串匹配的KMP算法

定义:

一大串字符串里找某字段算法

原理:

利用某字段自身特有的规律(前后缀,这个词有看上面那文章或了解过算法的人才知道我说啥),实现非暴力查找字符串的方法。

重点:

得到部分匹配表

心得:

我用js根据思路写了个模拟的代码,能用!
源码地址:戳我

效率

嗯。。。没js自带的indexOf快。
测试时我的代码x ms,indexOf 是 0.x ms,快一倍(废话,原生的肯定用了更好的算法,比如从两头开始算,我这只从一头开始算)。

题外话

为什么会接触这个算法呢,本来我在看别人的源码,然后不小心点到他的知乎,又不小心点到他点过赞的文章,然后看到个文章大概是有个人面试时手写了kmp算法,面试官还问他是不是hr漏题了呵呵之类。。。,然后我正事没做(买了个慕课网的vue视频),就去看这算法了,发现别人的代码理解不了,然后去看阮一峰的博客,哦思想懂了!然后尝试写代码,index索引不太清楚该+1还是-1什么的就拿笔画一画,整个过程用3,4小时(我就是这渣渣水平)。

心态变化:我擦好难-我还看吗-不知浪不浪费时间-别人源码写的啥-理解这思路-自己写写看-成功-开心

想着对学习的朋友说下,有时看不懂别人的代码不要心急,可能。。。你理解后自己能写出来,再去看别人的代码(或不看)也可以哦,我是这样过来的,一起加油!

DOM 中 Property 和 Attribute 的区别

刚刚偶然看到篇文章:
DOM 中 Property 和 Attribute 的区别
(强烈推荐先看完上文)
收获颇多,写写读后感跟注意到的点吧。

值得一提的是一般在表单中我们会用obj.value = xx或者用jq$(obj).value(xx)来改变input标签的值(这里的obj指input对象),改完后发现查看源代码中的input标签的value值还是原来的值,这个其实并不大会影响到我们提交的操作(这里适用于jq的表单serialize化)。
比如我们写了个input标签,id为'ha'
一顿操作后value值在浏览器界面是看到改变了,标签里的值还是没有变,这时我用jq的ajax+serialize提交表单
然后在浏览器f12后,network里看到
提交的值为2,也就是修改后的值。

其实看完那篇文章较大的收获还是通过jq源码了解了一些规范的函数写法
比如定义函数时

// 这是一个xx功能的函数,能够balalal

// @param a, a的定义
// @param b, b的定义
function test(a,b){
    //这里虽然参数有了b,但有时候不是为了传参用的,而是为了跟清楚的知道每个参数的定义
    //而不是如下这样写
    var b = xx;//bad
    //不用声明,直接
    b = xx;//good
}

后来我想了下,这只是让我知道了有这种写法而已,函数里变量一多都写到函数参数上面也不好看。嗯。。。就这样吧。

Jquery.extend与Object.assign

插曲

说到Jquery.extend就想到$.fn.extend,两者区别大了

前者可以把对象参数里的值加到jquery这个变量上,后者是把值加到jquery实例化后的对象上($.fn===$.prototype哦)。所以后者用于给jq扩展插件用的。

正言

$.extend一般情况下用起来跟Object.assign没什么不同
作用就是简单的便利每个对象参数里的key,相同则以后面对象参数(b)的key对应的value值覆盖前面(a)的key对应的value值。
这种方法经常被来用实例化组件时填写自定义的option来替换默认的option。(没听过的话,这里有个jq插件的源码,https://github.com/alvarotrigo/pagePiling.js/blob/master/jquery.pagepiling.js ,看到里面$.extend的应用就会明白了)。
如何你有看上面插件的源码,你会发现有点不一样的地方:$.extend(true,xxx,xxx)

没错,这次第一个参数为true后,对象参数不是简单的合并了,它会判断具体是哪里不一样,最后返回一个完整的对象(一般这才是我们想要的)。想写这篇文章也是从这插件的源码有感而来
那么利用Object.assign怎么实现该效果呢
刚写了个:
https://github.com/Newbit13/pika/blob/master/trueAssign.js
没事赞一下呗。

再附上一篇文章,lodash没怎么用过,所以给大家看看就好Lodash 中 assign,extend 和 merge 的区别

ES6的箭头函数this指向

参考ES6 箭头函数中的 this?你可能想多了(翻译)
ES6的箭头函数的this指向我认为所在的作用域属于谁就指向谁

        b={
            c:{
                d:function(){
                    var e = ()=>{
                        console.log(this);//打印c
                    }
                    e()
                }
            }
        }
        b.c.d();
    /******************************************************/
        b={
            c:function(){
                var e = ()=>{
                console.log(this);//打印b
                }
                e()
            }
        }
        b.c();
/******************************************************/
        b={
            c:()=>{
                console.log(this);//打印window
            }
        }
        b.c();

完。

正则小进阶

分组,断言详解
对于有正则基础的同学,
配合上面的参考文献,
()分组配合\数字的引用 (?=n)、(?!n)这种前向断言 (?<=n)、(?<!n)这种后向断言。嗯,正则基本够用了。ps:js里没有后向断言!!!s里没有后向断言!!!s里没有后向断言!!!气的昏古七
完。(额,好像断言的名字跟参考文献里作者提的不同,算了 我就喜欢这么叫它,只是为了好记哈哈)

js的面向对象编程

这里只贴出参考文献,按顺序看就好。
so easy!
详解JS类概念的实现
然后看看阮一峰老人家的三篇系列:
Javascript 面向对象编程(一):封装
最后看着玩的一篇,如果前面的理解过了,那么你可以发现这篇一些问题。(看不出问题去看评论= =):
Javascript定义类(class)的三种方法

我总结下,关于继承在JS实现的技术上只有两点要提:
1.为了继承父级私有属性,apply很重要。
2.为了不让父级的私有属性污染子集的原型,new构造函数很重要。
最后提醒,constructor记得指回正确的构造函数。

如果你还是真的真的真的不能理解为什么要这样做?
那就试着理解下这句话

“子类继承父类后:
一,子类的私有属性要继承父类的私有属性。私有的意思就是自己身上的,不用在原型链里找的
二,而父类的公共属性就通过原型链给子类用就好。”

完。

同源策略及规避方法

实现要贴的是来自大神阮一峰的参考文献:浏览器同源政策及其规避方法
然后是window.name的作用示例: window.name 跨域实现原理及实例
HTML5安全:CORS(跨域资源共享)简介。。。ie67不要想了。。。
看完以上文章觉得真是精彩,但有些知识点个人认为值得注意注意。
1. window.name容量为2mb,出现的目的是起初是为了解决cookie小的问题(80kb)
2. window.name在通讯前还是需要跳转到同源名下的网址,但window.name中的信息不变,进而实现通讯(结合上面第二个参考文献看,会发现和不能跨越的ajax配合,爽歪歪!!!)
3. ajax不能跨域?用cors可以,而且ie8支持(对于现在来说我认为一般ie8支持就算可以随便用了!),值得注意的是服务器需要设置Access-Control-Allow-Origin,如果是别人家的服务器。。。那么你就想想别的路子吧。(cors使用请参考开头提供的第三个文献)
4. 更方便简洁的方法是postMessage,h5的api,兼容性就呵呵啦。要注意的是该api的语法:
otherWindow.postMessage(message,targetOrigin, [transfer]);
其中特别特别特别注意otherWindow

MDN原文解释:otherWindow:其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。MDN原文解释:otherWindow:其他窗口的一个引用,比如iframe的contentWindow属性、执行window.open返回的窗口对象、或者是命名过或数值索引的window.frames。

这里第一次见到会有点措手不及,比如我给你个东西,主语应该是‘我’,这里是‘你’的感觉。。。

完。

我保证,超级超级简单的弄明白this指向

首先盗张图,来源:图解javascript this指向什么?

完。
好吧,其实我想介绍的是setTimeout和this之间的故事,也可以加深this的理解:)

obj={
    a:1,
    fn:function(){console.log(this.a)}//执行obj.fn()时打印1,此时this为obj。
}

obj={
    a:1,
    fn:function(){setTimeout(console.log(this.a),1000)}//执行obj.fn()时还是打印1,此时this为obj。
}
obj={
    a:1,
    fn:function(){setTimeout(function(){console.log(this.a)},1000)}//执行obj.fn()时还是打印undefined,此时this为window。
}

END