JS自省-4

191 阅读6分钟

前端自省系列😆有些是掘友的一些专栏文章的摘录,如果有不对的地方,请大家指出

FormData

概念

FormData接口提供一种表示表单数据的键值对的构造方式.可以通过JavaScript模拟表单控件操作.可以通过XMLHttpRequestsend方法异步提交表单

使用

FormData

初始化表单对象,可以传入dom元素,可以为空

//创建一个空的FormData对象
let formData = new FormData();
//创建一个存在的form对象 这个对象包含这个表单的数据
const formOne = document.getElementById("myform");
let formData = new FormData(formOne);

append,set

append:添加一个新值对到FormData对象,键存在将新值添加到值的集合中,不存在则添加新的键值对

set: 通append,区别在于如果键存在情况下,新的值覆盖旧值

//formData.append(name,value)
//formData.append(name,value,[filename])--value为文件对象时,可以通过filename定义文件名字如果value是Blob对象,默认文件名是"blob"
formData.append("name","lily");
formData.appen("name","hello"); //此时name的值是 lily,hello的集合
formData.append("avatar",fileInput.files[0],'avatar1.jpg') //上传头像文件,指定文件名称

//formData.set(name,value);
//formData.set(name,value,filename) //同append

delete

删除键值对

formData.delete("name");

entrieskeys

entries:返回FormData的键值对数据集合,是一个iterator对象

keys: 返回FormData的键集合,是一个iterator对象

const formOne = new FormData();
formData.entries(formOne);
formData.keys(formOne);

getgetAll

get: 返回指定key的第一个值

getAll: 返回指定key的所有值

formData.get("keyName");
formData.getAll("keyName");

has

检测某个key是否存在

formData.has("keyName")

values

返回一个允许遍历该对象中所有值的 迭代器

//创建一个FormData测试对象
var formData = new FormData();
formData.append('key1', 'value1');
formData.append('key2', 'value2');

//显示值
for (var value of formData.values()) {
   console.log(value); 
}
//value1
//value2

base64场景

  • 上传图片,可以转化为base64上传
  • 可以在页面显示base64图片,适应于不是很大的图
  • url加密

移动端点击事件延迟

移动端会延迟300ms,来判断是否还有下一次点击,以此来判定是点击还是双击

避免延迟

禁止缩放

<meta name="viewport" content="width=device-width user-scalable= 'no'">

fastclick.js

随机字符串

/**
 * 随即字符串
 * @param {Number} length 
 */
function randomString(length) {
    //如果转换的基数大于10,则会使用字母来表示大于9的数字,比如基数为16的情况,则使用a到f的字母来表示10到15
    //如果radix是36,就会把数字表示为由0-9, a-z组成的的36进制字符串
    let str = Math.random().toString(36).substr(2);
    if(str.length >= length) {
        return str.substr(0,length);
    }
    str += randomString((str.length) - length);
}

typeof null == "object"

不同的对象在底层都表示为二进制, 在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0, 自然前三位也是 0, 所以执行 typeof 时会返回“object”

在 javascript 的最初版本中,使用的 32 位系统,为了性能考虑使用低位存储了变量的类型信息:

  • 000:对象
  • 1:整数
  • 010:浮点数
  • 100:字符串
  • 110:布尔

九九乘法表

/**
 * 九九乘法表
 */
function nine() {
  let result = "";
  for (let index = 1; index <= 9; index++) {
    for (let i = 1; i <= index; i++) {
      result += `${i} x ${index} = ${index * i} `;
    }
    result += `\t\n`;
  }
  return result;
}

console.log(nine());
/*
1 x 1 = 1 	
1 x 2 = 2 2 x 2 = 4 	
1 x 3 = 3 2 x 3 = 6 3 x 3 = 9 	
1 x 4 = 4 2 x 4 = 8 3 x 4 = 12 4 x 4 = 16 	
1 x 5 = 5 2 x 5 = 10 3 x 5 = 15 4 x 5 = 20 5 x 5 = 25 	
1 x 6 = 6 2 x 6 = 12 3 x 6 = 18 4 x 6 = 24 5 x 6 = 30 6 x 6 = 36 	
1 x 7 = 7 2 x 7 = 14 3 x 7 = 21 4 x 7 = 28 5 x 7 = 35 6 x 7 = 42 7 x 7 = 49 	
1 x 8 = 8 2 x 8 = 16 3 x 8 = 24 4 x 8 = 32 5 x 8 = 40 6 x 8 = 48 7 x 8 = 56 8 x 8 = 64 	
1 x 9 = 9 2 x 9 = 18 3 x 9 = 27 4 x 9 = 36 5 x 9 = 45 6 x 9 = 54 7 x 9 = 63 8 x 9 = 72 9 x 9 = 81 	
*/

浏览器同源策略

  • 相同协议,host,端口才是同源
  • 防止了CSRF的安全问题
  • 防止DOM操作的安全问题

JS延迟加载

  • defer属性
  • async属性
  • body之后
  • setTimeOut放到异步队列中

写一个暂停函数

/**
 * 
 * @param {Number} wait 微秒
 */
function sleep(wait) {
  return new Promise((resolve) => setTimeout(resolve, wait));
}

sleep(2000).then(() => {
  console.log(1);
});

代码解析

function test(){ 
    console.log(test.prototype);
    console.log(Object.getPrototypeOf(test));
    //如果函数返回的值是引用类型(对象)的值时,new运算符将返回这个值
    return test; 
} 
new test() instanceof Object; //true
new test() instanceof test; //false
//等价于
test instanceof test; //false
//test是一个Function,原型链为 Function.prototype -> Object.prototype -> null
//原型链上没有 test.prototype 出现,所以 test 并不是 test 的一个实例

随即打乱一个数组

/**
 * 洗牌算法-快速打乱数组顺序
 * 倒序循环这个数组
 * 取范围从1到n的随机数k
 * k与n交换
 * 直到循环至数组的首个元素
 */
function arrShuffle(arr) {
  const length = arr.length - 1;
  for (let n = length; n >= 0; n--) {
    let randomIndex = Math.floor(Math.random() * (n + 1));
    let randomArr = arr[randomIndex]; //随机数k
    //k与n交换
    arr[randomIndex] = arr[n];
    arr[n] = randomArr;
  }
  return arr;
}`

为什么{}+[]===0

  • {} 被当成一个独立的空代码块
  • 所以上述表达式等价于+[] = 0
  • 0 === 0

({}+[])等于什么

  • 加上括号后会当做表达式计算
  • {}和[]都不是字符串
  • {}->valueOf->返回对象本身->非原始值->toString->[object Object]
  • []->valueIOf->返回对象本身->非原始值->toString->""
  • "[object Object]" + " " = "[object Object]"

数组的交集,差集,补集,并集

const arr1 = [1, 3, 4];
const arr2 = [1, 2, 4, 5];
const setArr1 = new Set(arr1);
const setArr2 = new Set(arr2);
//交集
let intersect = arr1.filter((item) => setArr2.has(item));
//差集
let minus = arr1.filter((item) => !setArr2.has(item));
//补集
let complement = [
  ...arr1.filter((item) => !setArr2.has(item)),
  ...arr2.filter((item) => !setArr1.has(item)),
];
//并集
let union = Array.from(new Set([...arr1, ...arr2]));
console.log(intersect, "交集");
console.log(minus, "差集");
console.log(complement, "补集");
console.log(union, "并集");

//[ 1, 4 ] 交集
//[ 3 ] 差集
//[ 3, 2, 5 ] 补集
//[ 1, 3, 4, 2, 5 ] 并集

如何给li绑定事件(ul下有1000+个li)

//通过事件冒泡,在父元素ul上绑定事件
document.getElementById("ul-id").addEventListener("click",(e) => {
    if (e.target.tagName === "li") {
        console.log(e);
    }
})

"1,2,3,4"split()

split有两个参数,第一个参数是字符串或正则表达式,表明按照什么规则分隔字符串.如果为空,则将整个字符串返回.第二个参数规定分隔的数量

"1,2,3,4".split() -> ["1,2,3,4"]

"1234".split("",2) -> ["1,2"]

Ajax请求

/**
 * ajax请求
 * 不可跨域请求
 */
function ajax(params) {
  params = params || {};
  //要发送的数据
  params.data = params.data || {};
  //GET,POST
  params.type = (params.type || "get").toUpperCase();
  //格式化数据
  params.data = formatParams(params.data);

  let xhr = new XMLHttpRequest();
  xhr.onreadystatechange = function () {
    //4已接收到全部响应数据
    if (xhr.readyState === 4) {
      if (xhr.status >= 200 && xhr.status < 300) {
        let response = "";
        const responseType = xhr.getResponseHeader;
        //获取响应数据格式
        if (responseType === "application/json") {
          response = JSON.parse(xhr.responseText);
        } else if (responseType.indexOf("xml") !== -1 && xhr.responseXML) {
          response = xhr.responseXML;
        } else {
          response = xhr.responseText;
        }
        //成功回调函数
        params.success && params.success(response);
      } else {
        //失败回调函数
        params.error && params.error(status);
      }
    }
  };

  //true异步 false同步
  const asyncFlag = params.async || true;
  if (params.type === "GET") {
    xhr.open(params.type, params.url + "?" + params.data, true);
    xhr.send();
  } else {
    xhr.open(params.type, params.url, asyncFlag);
    xhr.setRequestHeader(
      "Content-Type",
      "application/x-www-form-urlencoded; charset=UTF-8"
    );
    xhr.send(params.data);
  }
}

/**
 * 数据格式化
 */
function formatParams(data) {
  let params = [];
  for (let name in data) {
    params.push(
      encodeURIComponent(name) + "=" + encodeURIComponent(data[name])
    );
  }
  //时间戳 防止缓存
  params.push("v=" + new Date().getTime());
  //name=a&pwd=1&v=时间戳微秒
  return params.join("&");
}

//示例
ajax({
  url: "http://www.baidu.com", //请求地址
  type: "GET", //请求类型 GET|POST
  data: { wd: "时间戳" }, //请求数据
  success: function (response) {
    // 成功回调
    console.log(JSON.parse(response));
  },
  error: function () {
    //失败回调
    console.log("失败");
  },
});

红绿灯循环

async function trafficLight(color, wait) {
  await new Promise((resolve) => {
    console.log(color);
    setTimeout(resolve, wait);
  });
}

async function runLight() {
  let i = 0;
  while (i < 3) {
    await trafficLight("红灯", 1000);
    await trafficLight("绿灯", 2000);
    await trafficLight("黄灯", 3000);
  }
}

runLight();