Skip to content

JavaScript 代码片段

移动端适配

window.onload = window.onresize = function(){
    var view_width = document.getElementsByTagName('html')[0].getBoundingClientRect().width;
    var _html = document.getElementsByTagName('html')[0];
    view_width>640?_html.style.fontSize = 640 / 16 + 'px':_html.style.fontSize = view_width / 16 + 'px';
    // 640/16=40 手机屏幕宽度640,在设置里设置1rem为40px
    // 手机屏幕宽度414,则414/16=?,用的416/16=26,在设置里设置1rem=26px;
    // 最好在iconfont.css中的font-size大小改成一样的26px;将iconfont.css放在style.css上边,这样设置图标比较容易覆盖字体大小
    // 移动端&背景图
    $(function(){
        var windowWidth = $(window).width();//定义变量获取屏幕视口宽度
        if(windowWidth < 456){
            $('body').css('height','100%');
        }
    })
}

显示所有 dom 边框

[].forEach.call($$("*"), dom => {    dom.style.outline = "1px solid #" + (~~(Math.random() * (1 << 24))).toString(16);});
[]. forEach. call($$("*"), function(a){
      a. style. boxShadow ="0 0 5px #"+(~~(Math. random()*(1<<24))). toString(16)
      a. style . borderRadius = "5px" ;
   }
)

JavaScript 禁止查看页面源代码

window.onload = function(){
    //屏蔽键盘事件
    document.onkeydown = function (){
        var e = window.event || arguments[0];
        //F12
        if(e.keyCode == 123){
            return false;
        //Ctrl+Shift+I
        }else if((e.ctrlKey) && (e.shiftKey) && (e.keyCode == 73)){
            return false;
        //Shift+F10
        }else if((e.shiftKey) && (e.keyCode == 121)){
            return false;
        //Ctrl+U
        }else if((e.ctrlKey) && (e.keyCode == 85)){
            return false;
        }
    };
    //屏蔽鼠标右键
    document.oncontextmenu = function (){
        return false;
    }
}

JSON

JSON 指的是 JavaScript 对象表示法(JavaScript Object Notation)
JSON 是轻量级的文本数据交换格式
JSON 是存储和交换文本信息的语法,类似 XML。
JSON 比 XML 更小、更快,更易解析。

JSON 实例
{
    "sites": [
    { "name":"菜鸟教程" , "url":"www.runoob.com" },
    { "name":"google" , "url":"www.google.com" },
    { "name":"微博" , "url":"www.weibo.com" }
    ]
}

JSON 语法规则
JSON 语法是 JavaScript 对象表示语法的子集。

数据在名称/值对中
数据由逗号分隔
大括号 {} 保存对象
中括号 [] 保存数组,数组可以包含多个对象

对象和数组的循环,嵌套,修改,删除--菜鸟教程

JSON.parse()
我们可以使用 JSON.parse() 方法将数据转换为 JavaScript 对象。
{ "name":"runoob", "alexa":10000, "site":"www.runoob.com" }
我们使用 JSON.parse() 方法处理以上数据,将其转换为 JavaScript 对象:
var obj = JSON.parse('{ "name":"runoob", "alexa":10000, "site":"www.runoob.com" }');

JSON.stringify()
将 JavaScript 对象转换为 JSON 字符串
var obj = { "name":"Runoob", "alexa":function () {return 10000;}, "site":"www.runoob.com"};
obj.alexa = obj.alexa.toString();// 解析函数
var myJSON = JSON.stringify(obj);// 解析js对象为字符串

JSON 使用
把 JSON 文本转换为 JavaScript 对象
JSON 最常见的用法之一,是从 web 服务器上读取 JSON 数据(作为文件或作为 HttpRequest),将 JSON 数据转换为 JavaScript 对象,然后在网页中使用该数据。
由于 JSON 语法是 JavaScript 语法的子集,JavaScript 函数 eval() 可用于将 JSON 文本转换为 JavaScript 对象。
eval() 函数使用的是 JavaScript 编译器,可解析 JSON 文本,然后生成 JavaScript 对象。必须把文本包围在括号中,这样才能避免语法错误。

函数

函数声明方式
function add(num1,num2){
    return num1+num2;
  }
console.log(add(3, 5));

var + 函数表达式声明方式
var add= function(num1,num2){
                      return num1+num2;
      }; 
console.log(add(3, 5));

立即执行函数
    (function () {
        console.log("hello world");
    })();

匿名函数作为参数
    function test(fn) {
        fn();
    }
    test(function () {
        console.log("hello world");
    });

匿名函数作为返回值
    function test() {
        return function () {
            console.log("hello world");
        }
    }
    var res = test();
    res();

箭头函数
是函数的一种简写方式,类似于匿名函数
()内是参数,一个参数的时候,()可以省略,=>后是返回值,省略了return。
词法作用域,不会绑定this;箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的。
使用 const 比使用 var 更安全,因为函数表达式始终是一个常量。
箭头函数的写法:
// ES5
var x = function(x, y) {
     return x * y;
}
// ES6
const x = (x, y) => x * y;
箭头函数的写法:
// ES5
function (x) {
    return x * x;
}
// ES6
x => x * x

如果函数部分只是一个语句,则可以省略 return 关键字和大括号 {},这样做是一个比较好的习惯。
以下两者等价
const x = (x, y) => x * y;
const x = (x, y) => { return x * y };

如果要返回一个对象,就要注意,如果是单表达式,这么写的话会报错:
x => { foo: x }
因为和函数体的{ ... }有语法冲突,所以要改为:
x => ({ foo: x })

// 两个参数:
(x, y) => x * x + y * y
// 无参数:
() => 3.14
// 可变参数:
(x, y, ...rest) => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    }
    return sum;
}

钩子函数
React和Vue,里面有生命周期函数,说的是一个页面不同时期执行的函数,那些都是钩子函数。

回调函数
回调,回调,就是回头调用的意思。主函数的事先干完,回头再调用传进来的那个函数。

//定义主函数,回调函数作为参数
function A(callback) {
    callback();
    console.log('我是主函数');
}
//定义回调函数
function B(){
    setTimeout("console.log('我是回调函数')", 3000);//模仿耗时操作
}
//调用主函数,将函数B传进去
A(B);
//输出结果
我是主函数
我是回调函数(过三秒后出现)

回调函数都用在耗时操作上面:因为主函数不用等待回调函数执行完,可以接着执行自己的代码。比如ajax请求,比如处理文件等。

函数的提升
提升(Hoisting)是 JavaScript 默认将当前作用域提升到前面去的的行为,就是函数可以在声明之前调用
console.log(myFunction(5));
function myFunction(y) {
    return y * y;
}
结果:
25

匿名函数没有提升,相当于变量的提升,函数的提升优先级高于变量的提升
getName();
var getName=function(){
    console.log(2);
}
function getName(){
    console.log(1);
}
getName();
结果:
1
2

JavaScript 闭包

要理解闭包,首先必须理解Javascript特殊的变量作用域。
变量的作用域无非就是两种:全局变量和局部变量。
Javascript语言的特殊之处,就在于函数内部可以直接读取全局变量。
  var n=999;
  function f1(){
    alert(n);
  }
  f1(); // 999
另一方面,在函数外部自然无法读取函数内的局部变量。
  function f1(){
    var n=999;
  }
  alert(n); // error
这里有一个地方需要注意,函数内部声明变量的时候,一定要使用var命令。如果不用的话,你实际上声明了一个全局变量!
  function f1(){
    n=999;
  }
  f1();
  alert(n); // 999
如何从外部读取局部变量?
出于种种原因,我们有时候需要得到函数内的局部变量。但是,前面已经说过了,正常情况下,这是办不到的,只有通过变通方法才能实现。
那就是在函数的内部,再定义一个函数。
  function f1(){
    var n=999;
    function f2(){
      alert(n); // 999
    }
  }
在上面的代码中,函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的。但是反过来就不行,f2内部的局部变量,对f1就是不可见的。这就是Javascript语言特有的"链式作用域"结构(chain scope),子对象会一级一级地向上寻找所有父对象的变量。所以,父对象的所有变量,对子对象都是可见的,反之则不成立。
既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,我们不就可以在f1外部读取它的内部变量了吗!
  function f1(){
    var n=999;
    function f2(){
      alert(n);
    }
    return f2;
  }
  var result=f1();
  result(); // 999
闭包的概念:
上一节代码中的f2函数,就是闭包。
闭包就是能够读取其他函数内部变量的函数。
由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。
所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。

Session、Cookie 和 Token

cookie和session的区别
1、cookie数据存放在客户的浏览器上,session数据放在服务器上.
2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗考虑到安全应当使用session。
3、设置cookie时间可以使cookie过期。但是使用session-destory(),我们将会销毁会话。
4、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能考虑到减轻服务器性能方面,应当使用cookie。
5、单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie。(Session对象没有对存储的数据量的限制,其中可以保存更为复杂的数据类型)
session很容易失效,用户体验很差;
虽然cookie不安全,但是可以加密 ;
cookie也分为永久和暂时存在的;
浏览器 有禁止cookie功能 ,但一般用户都不会设置;
一定要设置失效时间,要不然浏览器关闭就消失了;
例如:
记住密码功能就是使用永久cookie写在客户端电脑,下次登录时,自动将cookie信息附加发送给服务端。
application是全局性信息,是所有用户共享的信息,如可以记录有多少用户现在登录过本网站,并把该信息展示个所有用户。
两者最大的区别在于生存周期,一个是IE启动到IE关闭.(浏览器页面一关 ,session就消失了),一个是预先设置的生存周期,或永久的保存于本地的文件。(cookie)
Session信息是存放在server端,但session id是存放在client cookie的,当然php的session存放方法是多样化的,这样就算禁用cookie一样可以跟踪
Cookie是完全保持在客户端的如:IE firefox 当客户端禁止cookie时将不能再使用

Token
Token的引入:Token是在客户端频繁向服务端请求数据,服务端频繁的去数据库查询用户名和密码并进行对比,判断用户名和密码正确与否,并作出相应提示,在这样的背景下,Token便应运而生。
Token的定义:Token是服务端生成的一串字符串,以作客户端进行请求的一个令牌,当第一次登录后,服务器生成一个Token便将此Token返回给客户端,以后客户端只需带上这个Token前来请求数据即可,无需再次带上用户名和密码。
使用Token的目的:Token的目的是为了减轻服务器的压力,减少频繁的查询数据库,使服务器更加健壮。
基于 Token 的身份验证:
使用基于 Token 的身份验证方法,在服务端不需要存储用户的登录记录。流程是这样的:
客户端使用用户名跟密码请求登录
服务端收到请求,去验证用户名与密码
验证成功后,服务端会签发一个 Token,再把这个 Token 发送给客户端
客户端收到 Token 以后可以把它存储起来,比如放在 Cookie 里或者 Local Storage 里
客户端每次向服务端请求资源的时候需要带着服务端签发的 Token
服务端收到请求,然后去验证客户端请求里面带着的 Token,如果验证成功,就向客户端返回请求的数据
APP登录的时候发送加密的用户名和密码到服务器,服务器验证用户名和密码,如果成功,以某种方式比如随机生成32位的字符串作为token,存储到服务器中,并返回token到APP,以后APP请求时,
凡是需要验证的地方都要带上该token,然后服务器端验证token,成功返回所需要的结果,失败返回错误信息,让他重新登录。其中服务器上token设置一个有效期,每次APP请求的时候都验证token和有效期。

首次登录时,后端服务器判断用户账号密码正确之后,根据用户id、用户名、定义好的秘钥、过期时间生成 token ,返回给前端;
前端拿到后端返回的 token ,存储在 localStorage 和 Vuex 里;
前端每次路由跳转,判断 localStorage 有无 token ,没有则跳转到登录页,有则请求获取用户信息,改变登录状态;
每次请求接口,在 Axios 请求头里携带 token;
后端接口判断请求头有无 token,没有或者 token 过期,返回401;
前端得到 401 状态码,重定向到登录页面。

第一次登陆后保存token
之后每次请求数据请求头携带token
如果token已经过期,下一次请求数据再判断重新登陆

首次登录时,后端服务器判断用户账号密码正确之后,根据用户id、用户名、定义好的秘钥、过期时间生成 token ,返回给前端;
前端拿到后端返回的 token ,存储在 localStorage 和 Vuex 里;
前端每次路由跳转,判断 localStorage 有无 token ,没有则跳转到登录页,有则请求获取用户信息,改变登录状态;
每次请求接口,在 Axios 请求头里携带 token;
后端接口判断请求头有无 token,没有或者 token 过期,返回401;
前端得到 401 状态码,重定向到登录页面。

第一次登陆后保存token
之后每次请求数据请求头携带token
如果token已经过期,下一次请求数据再判断重新登陆

下载函数

不能更改文件名:

downloadFile(fileUrl, fileName) {
  const link = document.createElement('a')
  link.href = fileUrl
  link.download = fileName || 'file'
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
},

可更改文件名

方法 1:使用 fetch

js
export const downloadFile = (fileUrl, fileName) => {
  fetch(fileUrl)
    .then((response) => response.blob())
    .then((blob) => {
      const link = document.createElement("a");
      link.href = URL.createObjectURL(blob);
      link.download = fileName || "file";
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
      URL.revokeObjectURL(link.href);
    });
};

方法 2:使用 XMLHttpRequest

js
export const downloadFile = (fileUrl, fileName) => {
  const xhr = new XMLHttpRequest();
  xhr.open("GET", fileUrl, true);
  xhr.responseType = "blob";
  xhr.onload = function () {
    const blob = this.response;
    const link = document.createElement("a");
    link.href = URL.createObjectURL(blob);
    link.download = fileName || "file";
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
    URL.revokeObjectURL(link.href);
  };
  xhr.send();
};

使用正则表达式匹配以数字+顿号、数字+点号、中文大写数字+顿号、中文大写数字+点号开头的模式

const itemList = string.split(/\d、|\d\.|[一二三四五六七八九十零]、|[一二三四五六七八九十零]\./).filter(Boolean);
console.log(itemList);