_] javascript的表达式“总价钱是”+800+“元”的结果是( )。 a. 一">
当前位置:   article > 正文

前端面试题(七)(JS篇)建议收藏,持续更新中..._] javascript的表达式“总价钱是”+800+“元”的结果是( )。 a. 一条错误消息 b

] javascript的表达式“总价钱是”+800+“元”的结果是( )。 a. 一条错误消息 b.

请使用js实现一个秒表计时器的程序

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>计时器</title>
  8. </head>
  9. <body>
  10. <div id="counter"></div>
  11. </body>
  12. </html>
  13. <script>
  14. /* 选中所需要的couter */
  15. const ele = document.getElementById('counter');
  16. /* 定义两个变量 */
  17. let intervalId, seconds;
  18. /* 定义一个计算时间的方法 */
  19. function counter() {
  20. /* 定义定时器 */
  21. intervalId = window.setInterval(() => {
  22. --seconds;
  23. ele.innerText = seconds;
  24. if (seconds === 0) {
  25. alert('计时结束');
  26. window.clearInterval(intervalId);
  27. }
  28. }, 1000);
  29. }
  30. function stopCounter() {
  31. window.clearInterval(intervalId);
  32. }
  33. function resumeCounter() {
  34. counter();
  35. }
  36. seconds = 100;
  37. counter();
  38. </script>

 运行结果
在这里插入图片描述

模拟 localStorage 时如何实现过期时间功能

  1. 1.存储时记录下有效截止时间
  2. 2.取数据时判断是否超过有效时间,在有效期内则返回,不在则提示或返回空并且将其删除
  1. class MyStorage {
  2. get(key) {
  3. const wrapValue = localStorage.getItem(key)
  4. if (wrapValue == null) {
  5. return undefined
  6. }
  7. const {value, expires} = JSON.parse(wrapValue)
  8. - if ((expires != null && Date.now() < expires) || expires == null) {
  9. + if (!expires || Date.now() < expires) {
  10. return value
  11. }
  12. -
  13. + localStorage.rmeoveItem(key)
  14. return undefined
  15. }
  16. set(key, value, period) {
  17. const wrapValue = { value };
  18. if (period != null) {
  19. wrapValue.expires = Date.now() + period;
  20. }
  21. localStorage.setItem(key, JSON.stringify(wrapValue));
  22. }
  23. }

请使用js实现商品的自由组合,并说说你的思路

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>商品sku</title>
  8. </head>
  9. <body>
  10. </body>
  11. </html>
  12. <script>
  13. var a = ['黄', '绿']
  14. var b = ['s', 'l']
  15. var c = ['大', '小']
  16. function decar(...args) {
  17. return args.reduce((acc, item) => {
  18. const res = []
  19. for (let i = 0; i < acc.length; i++) {
  20. for (let j = 0; j < item.length; j++) {
  21. const prev = [].concat(acc[i])
  22. res.push([...prev, item[j]])
  23. }
  24. }
  25. return res
  26. })
  27. }
  28. decar(a, b, c)
  29. console.log(decar(a, b, c))
  30. </script>

运行结果
在这里插入图片描述

js中的undefined和 ReferenceError: xxx is not defined 有什么区别?

  1. undefined是变量已声明,但未赋值
  2. ReferenceError: xxx is not defined 是xxx未声明,使用了不存在的变量
  3. JavaScript Number.toPrecision() 函数详解
  4. JavaScript:
  5. numberObject.toPrecision( [ precision ] )
  6. 如果没有提供precision参数或其值为undefined,则将转而调用toString()方法进行处理。
  7. 如果提供了参数,则参数precision必须介于 [1, 21] 之间,否则将报错。
  8. 如果数字的有效位数大于precision,将会根据第precision + 1位的有效数字进行四舍五入。
  9. 返回值
  10. toPrecision()函数的返回值为String类型,返回该数字以指数计数法或定点表示法的表示形式。如果该数字的有效位数小于precision位,则在小数部分填充相应位数的0
  11. 如果参数precision大于等于数字整数部分的位数,则返回值将采用定点表示法;否则将采用指数计数法。
  12. 有效数字的位数是从数字第一个不为0的数(包括整数部分和小数部分)开始计算的位数。 


示例&说明

  1. JavaScript:
  2. //toPrecision()会进行四舍五入
  3. var num = 423.536;
  4. // 调用的是toString()方法
  5. document.writeln( num.toPrecision() ); // 423.536
  6. num = 562345.12456;
  7. // 由于整数部分有6位,要求只有3位有效数字,必须采用指数计数法才能表示。
  8. document.writeln( num.toPrecision( 3 ) ); // 5.62e+5
  9. num = -2651.10;
  10. // 整数部分有4位,要求的有效数字为4位,采用定点表示法
  11. document.writeln( num.toPrecision( 4 ) ); // -2651
  12. num = 4564561.12457;
  13. // 整数部分有7位,要求有效数字为1位,采用指数计数法
  14. document.writeln( num.toPrecision( 1 ) ); // 5e+6
  15. num = 231;
  16. // 整数部分有3位,要求有效数字为5位,采用定点表示法,并在小数部分填充两个0
  17. document.writeln( num.toPrecision( 5 ) ); // 231.00



 

获取浏览器当前页面的滚动条高度的兼容写法

document.documentElement.scrollTop || document.body.scrollTop;

一道变态题 Number.call.call(Number, undefined, 0) 等于什么?

  1. call 的第一个参数用于改变上下文,由于没有用到 this,第一个参数 Number 实际上没有用。
  2.     Number.call(Number, undefined, 0) 等价于 Number(undefined, 0),由于 Number 只会接受第一个参数。
  3.     Number.call.call(Number, undefined, 0) 等价于 Number.call(undefined, 0),也就是 Number(0)。

ReferenceError和TypeError有什么区别?

ReferenceError

指的是引用出错,比如尝试访问未定义的变量,或者提前访问无提升的变量,都会引发这个错误:

  1. console.log(foo); // ReferenceError: foo is not defined
  2. let foo = 1;
  3. TypeError

指的是类型出错。

众所周知JavaScript是一个弱类型的语言,这既是它的优点,也经常被人诟病。你永远也不知道 a + b 是在做数值加减还是字符串拼接,而且似乎 a + b 几乎从来也不会报错。

而tc39自 ES5 到 ES6 以来,将 TypeError 的频率几乎翻了4倍之多。目的就是为了规范和强调类型这一概念,避免过于模糊类型这一概念导致JavaScript对于语义的不确定性。
 

  1. Symbol() + 1; // TypeError: Cannot convert a Symbol value to a number
  2. ({ toString: () =>({}) }) + 'a'; // TypeError: Cannot convert object to primitive value

这样使得JavaScript更为规范,当一个方法的参数需要一个 number 但却收到了一个 object,与其让它返回 NaN,不如果断地抛出 TypeError 吧。

  1. 如何避免JS浮点运算的精度问题(例:0.1+0.7=0.7999999999999999
  2.  function precision(num1,num2){
  3.         num1Length = num1.toString().length;
  4.         num2Length = num2.toString().length;
  5.         let len =  num1Length > num2Length ? num1Length : num2Length;
  6.         return (num1 + num2).toPrecision(len);
  7.     }
  8.     console.log(precision(0.1,0.7));

JavaScript Number.toPrecision() 函数详解

JavaScript:

numberObject.toPrecision( [ precision ] )

如果没有提供precision参数或其值为undefined,则将转而调用toString()方法进行处理。
如果提供了参数,则参数precision必须介于 [1, 21] 之间,否则将报错。
如果数字的有效位数大于precision,将会根据第precision + 1位的有效数字进行四舍五入。
返回值

toPrecision()函数的返回值为String类型,返回该数字以指数计数法或定点表示法的表示形式。如果该数字的有效位数小于precision位,则在小数部分填充相应位数的0。

如果参数precision大于等于数字整数部分的位数,则返回值将采用定点表示法;否则将采用指数计数法。
 

有效数字的位数是从数字第一个不为0的数(包括整数部分和小数部分)开始计算的位数。 

示例&说明
 

  1. JavaScript:
  2. //toPrecision()会进行四舍五入
  3. var num = 423.536;
  4. // 调用的是toString()方法
  5. document.writeln( num.toPrecision() ); // 423.536
  6. num = 562345.12456;
  7. // 由于整数部分有6位,要求只有3位有效数字,必须采用指数计数法才能表示。
  8. document.writeln( num.toPrecision( 3 ) ); // 5.62e+5
  9. num = -2651.10;
  10. // 整数部分有4位,要求的有效数字为4位,采用定点表示法
  11. document.writeln( num.toPrecision( 4 ) ); // -2651
  12. num = 4564561.12457;
  13. // 整数部分有7位,要求有效数字为1位,采用指数计数法
  14. document.writeln( num.toPrecision( 1 ) ); // 5e+6
  15. num = 231;
  16. // 整数部分有3位,要求有效数字为5位,采用定点表示法,并在小数部分填充两个0
  17. document.writeln( num.toPrecision( 5 ) ); // 231.00

举例说明js立即执行函数的写法有哪些?

  1. 1、(function(){
  2. //code
  3. }())
  4. 2、!function(){
  5. //code
  6. }()
  7. 3、!(function(){
  8. //code
  9. })()
  10. 4、!(()=>{
  11. //code
  12. })()

for in 和 for of 的区别? 

  1. for of 用于遍历于数组和可迭代对象得到的是entity({key: value}), for in 用于遍历对象的得到的是对象的属性名
  2. for in 不可用来遍历一个数组, for in 将会把数组中的 length 等不需要的属性给一并遍历出来
  3. for of 不可用来遍历对象,对象是一个不可迭代对象。

写一个方法判断数组内元素是否全部相同

  1. const isSameArray = function (array) {
  2. if (Array.isArray(array)) {
  3. return new Set(array).size === 1;
  4. }
  5. return false;
  6. };

说说防止重复发送ajax请求的方法有哪些?各自有什么优缺点? 

  1. // 方法一 防抖
  2. function debounce(f, ms) {
  3. let time;
  4. return function(){
  5. let arg = Array.prototype.slice.call(arguments, 1);
  6. if(time) {
  7. clearTimeout(time);
  8. }
  9. time = setTimeout(function(){
  10. f.apply(this, arg)
  11. },ms)
  12. }
  13. }
  14. // 方法二 节流
  15. function throttle(f, ms){
  16. let lastTime = 0;
  17. return function(){
  18. let arg = Array.prototype.slice.call(arguments, 1);
  19. let newTime = Date.now();
  20. if(newTime-lastTime > ms) {
  21. setTimeout(function(){
  22. f.apply(this, arg)
  23. },ms)
  24. }
  25. lastTime = newTime;
  26. }
  27. }
  1. 防抖法:在一段时间内重复请求,则取消本次请求
  2. 节流法:在一段时间内只能请求一次,下次请求必须在前一次请求完成后
  3. 等值法:未完成请求状态不再请求,而是完成后直接返回相同的内容

 请使用 js 实现一个双向链表

start


链表结构是我们在面试中经常会被问起的较为基础的数据结构问题,起初学习数据结构使用的是C++语言,最近在做前端面试题的过程中没碰到了需要用js实现双链表的需求,百度出来的文章发现可很多错误,于是索性自己重新写了,并且列出了一些错误点,这里给大家较为详细的一步步看一下实现思想和步骤,相较于C++语言,js的实现可以说是很简单了,不需要创建繁琐的对象,更加直观易懂;
首先我们来看一下双向链表的结构图:
在这里插入图片描述
每个结点包含三部分,指向前一个结点的指针(pre),指向后一个节点的指针(next),以及自己的数据部分(element),于是我们就可以先写出结点对象

function Node:定义结点对象

  1. function Node(element) {
  2. this.element = element
  3. this.next = null
  4. this.previous = null
  5. }

然后我们开始实现插入链表的算法
在这里插入图片描述

(声明)下面函数中的this是我们最后初始化链表的实例,这里大家不要疑惑。可以拉到最下面我们初始化链表那里,相信你会明白呦

  1. **`function insert`:插入节点**
  2. function insert(newelement, currentelement) {
  3. var newNode = new Node(newelement)
  4. var currentNode = this.find(currentelement)
  5. if (currentNode === 'error') {
  6. console.log('无法插入,要插入节点不存在')
  7. return
  8. }
  9. if (currentNode.next != null) {
  10. newNode.next = currentNode.next
  11. currentNode.next = newNode
  12. newNode.previous = currentNode
  13. newNode.next.previous = newNode
  14. } else {
  15. currentNode.next = newNode
  16. newNode.previous = currentNode
  17. }
  18. }

function find:找到插入位置 

  1. function find(element) {
  2. var currentNode = this.head
  3. while (currentNode.element != element) {
  4. /*如果找到最后一个节点还没有找到我们的插入点,那么我们就会返回错误*/
  5. if (currentNode.next == null) {
  6. console.log('can not find this node; maybe not have this node')
  7. return 'error'
  8. }
  9. currentNode = currentNode.next
  10. }
  11. return currentNode
  12. }

接下来是移除结点的实现,如果看懂了插入节点的实现,那么移除就会很简单了,相信大家都可以很快明白,这里就直接贴出实现代码; 

  1. function remove:移除一个结点
  2. function remove(element) {
  3. var currentNode = this.find(element)
  4. if (currentNode === 'error') {
  5. console.log('要移除节点不存在')
  6. return
  7. }
  8. /*首先是不是头尾节点的情况*/
  9. if (currentNode.next != null && currentNode.previous != null) {
  10. currentNode.previous.next = currentNode.next
  11. currentNode.next.previous = currentNode.previous
  12. currentNode.next = null
  13. currentNode.previous = null
  14. } else if (currentNode.previous == null) {
  15. /*当是头节点的时候*/
  16. this.head = currentNode.next
  17. currentNode.next.previous = null
  18. currentNode.next = null
  19. } else if (currentNode.next == null) {
  20. /*当是尾节点的时候 */
  21. currentNode.previous.next = null
  22. currentNode.previous = null
  23. }
  24. }

截止到这里我们基本功能已经有了,下面使我们根据自己需要可以自定义一些其他函数 

  1. function lastNode:找到最后一个节点
  2. function lastNode() {
  3. var head = this.head
  4. while (head.next != null) {
  5. head = head.next
  6. }
  7. return head //这里head在尾节点的位置
  8. }
  1. function append:将要添加的结点放在链表末尾
  2. function append(element) {
  3. var lastnode = this.lastNode()
  4. var newNode = new Node(element)
  5. lastnode.next = newNode
  6. newNode.previous = lastnode
  7. }
  1. function showlist:将链表所有的结点打印出来
  2. function showlist() {
  3. var head = this.head
  4. do {
  5. console.log(head.element)
  6. head = head.next
  7. } while (head != null)
  8. // 大家可以看一下下面注释内容存在什么问题,留给大家思考一下
  9. // while (head.next != null) {
  10. // console.log(head.element)
  11. // head = head.next
  12. // }
  13. }

接下来是对链表进行初始化,这也是上述函数中所有this所代表的实例

function initlist:初始化链表,并将所有方法注册到链表中

  1. function initlist() {
  2. this.head = new Node('one')
  3. this.find = find
  4. this.insert = insert
  5. this.remove = remove
  6. this.showlist = showlist
  7. this.lastNode = lastNode
  8. this.append = append
  9. }
  10. var list = new initlist()
  11. list.insert('two', 'one')
  12. list.insert('four', 'two')
  13. list.insert('three', 'two')
  14. // console.log(list.head.next)
  15. list.showlist()
  16. list.append('A')
  17. list.append('B')
  18. list.insert('B2', 'B')
  19. list.showlist()
  20. console.log(list.lastNode())
  21. // list.remove('one')
  22. // list.showlist()
  23. console.log(list.find('A').previous)
  24. // console.log(list.find('four').previous)
  25. // console.log(list.head.element)

下面是运行结果:
在这里插入图片描述
源码: 

  1. function Node(element) {
  2. this.element = element
  3. this.next = null
  4. this.previous = null
  5. }
  6. function find(element) {
  7. var currentNode = this.head
  8. while (currentNode.element != element) {
  9. if (currentNode.next == null) {
  10. console.log('can not find this node; maybe not have this node')
  11. return 'error'
  12. }
  13. currentNode = currentNode.next
  14. }
  15. return currentNode
  16. }
  17. function insert(newelement, currentelement) {
  18. var newNode = new Node(newelement)
  19. var currentNode = this.find(currentelement)
  20. if (currentNode === 'error') {
  21. console.log('无法插入,要插入节点不存在')
  22. return
  23. }
  24. if (currentNode.next != null) {
  25. newNode.next = currentNode.next
  26. currentNode.next = newNode
  27. newNode.previous = currentNode
  28. newNode.next.previous = newNode
  29. } else {
  30. currentNode.next = newNode
  31. newNode.previous = currentNode
  32. }
  33. }
  34. function remove(element) {
  35. var currentNode = this.find(element)
  36. if (currentNode === 'error') {
  37. console.log('要移除节点不存在')
  38. return
  39. }
  40. /*首先是不是头尾节点的情况*/
  41. if (currentNode.next != null && currentNode.previous != null) {
  42. currentNode.previous.next = currentNode.next
  43. currentNode.next.previous = currentNode.previous
  44. currentNode.next = null
  45. currentNode.previous = null
  46. } else if (currentNode.previous == null) {
  47. /*当是头节点的时候*/
  48. this.head = currentNode.next
  49. currentNode.next.previous = null
  50. currentNode.next = null
  51. } else if (currentNode.next == null) {
  52. /*当是尾节点的时候 */
  53. currentNode.previous.next = null
  54. currentNode.previous = null
  55. }
  56. }
  57. function showlist() {
  58. var head = this.head
  59. do {
  60. console.log(head.element)
  61. head = head.next
  62. } while (head != null)
  63. // while (head.next != null) {
  64. // console.log(head.element)
  65. // head = head.next
  66. // }
  67. }
  68. function initlist() {
  69. this.head = new Node('one')
  70. this.find = find
  71. this.insert = insert
  72. this.remove = remove
  73. this.showlist = showlist
  74. this.lastNode = lastNode
  75. this.append = append
  76. }
  77. function append(element) {
  78. var lastnode = this.lastNode()
  79. var newNode = new Node(element)
  80. lastnode.next = newNode
  81. newNode.previous = lastnode
  82. }
  83. function lastNode() {
  84. var head = this.head
  85. while (head.next != null) {
  86. head = head.next
  87. }
  88. return head
  89. }
  90. var list = new initlist()
  91. list.insert('two', 'one')
  92. list.insert('four', 'two')
  93. list.insert('three', 'two')
  94. // console.log(list.head.next)
  95. list.showlist()
  96. list.append('A')
  97. list.append('B')
  98. list.insert('B2', 'B')
  99. list.showlist()
  100. console.log(list.lastNode())
  101. // list.remove('one')
  102. // list.showlist()
  103. console.log(list.find('A').previous)
  104. // console.log(list.find('four').previous)
  105. // console.log(list.head.element)

 END


 ajax请求地址只支持http/https吗?能做到让它支持rtmp://等其它自定义协议吗 ?

  1. ajax只支持http/https协议,
  2. 可以通过自定义http头来间接支持自定义协议

请写一个性能最好的深度克隆对象的方法

  1. const deepClone = (obj) => {
  2.   const copy = obj instance Array ? [] : {};
  3.   for (let key in obj) {
  4.     if (obj.hasOwnProperty(key)) {
  5.        copy[key] = typeof obj[key] === 'object' ? deepClone(obj[key]) : obj[key]
  6.    }
  7.   }
  8. return copy;
  9. }

使用ajax请求真的不安全吗?为什么?

  1. AJAX是发送HTTP请求的一种方式,只不过浏览器给它加了一个同源策略而已。
  2. 所以从这一点可以得出一个结论:AJAX本质上安全性和HTTP请求一样

 你有使用过pjax吗?它的原理是什么?

pushState + ajax = pjax

 根据元素ID遍历树形结构,查找到所有父元素ID

  1. var list = [{
  2. "orgId": 1,
  3. "orgName": "校长办公室1",
  4. "parentId": 0
  5. },{
  6. "orgId": 2,
  7. "orgName": "校长办公室2",
  8. "parentId": 1,
  9. },{
  10. "orgId": 3,
  11. "orgName": "校长办公室3",
  12. "parentId": 2,
  13. }];
  14. function findParent(idx){
  15. list.forEach(item => {
  16. if (idx === item['orgId']){
  17. let pid = item['parentId']
  18. console.log(pid)
  19. findParent(pid)
  20. }
  21. })
  22. }
  23. findParent(3); //2 1 0

 举例说明Object.defineProperty会在什么情况下造成循环引用导致栈溢出?

  1. var data = {
  2. count: 1,
  3. value: 2
  4. }
  5. Object.defineProperty(data, 'count', {
  6. enumerable: true,
  7. configurable: true,
  8. get: function () {
  9. console.log('你访问了count', this.count); // 循环读取data.count 导致报错
  10. return this.value
  11. },
  12. set: function (newVal) {
  13. console.log('你设置了count');
  14. }
  15. })
  16. console.log(data.count) // 报错 Maximum call stack size exceeded

写一个方法,当给定数字位数不足8位时,则在左边补充0以补足8位数的方法 

  1. function padNumber(n, targetLen, placeholder) {
  2. const arr = ("" + n).split("");
  3. const diff = arr.length - targetLen;
  4. if (diff < 0) {
  5. return Array(0 - diff)
  6. .fill(placeholder, 0, 0 - diff + 1)
  7. .concat(arr)
  8. .join("");
  9. } else {
  10. return arr.join("");
  11. }
  12. }
  13. console.log(padNumber(3458, 8, "0")); //'00003458'
  14. console.log(padNumber(90990, 3, "-")); //'90990'

innerHTML与outerHTML有什么区别? 

  1. <div id="test"><h5>就是喜欢你</h5></div>
  2. document.getElementById("test").innerHTML //<h5>就是喜欢你</h5> document.getElementById("test").outHTML //<div id="test"><h5>就是喜欢你</h5></div>

js操作节点的方法有哪些? 

  1. 创建节点
  2. createElement() 创建一个元素节点
  3. createTextNode() 创建一个文本节点
  4. createAttribute() 创建一个属性节点
  5. createComment() 创建一个注释节点
  6. 插入节点
  7. appendChild() 把节点插入到父节点的末尾
  8. insertBefore() 把节点插入到父节点的某个兄弟节点的前面
  9. 删除节点
  10. removeChild()
  11. 查找节点
  12. getElementById()
  13. getElementsByTagName()
  14. getElementsByName()
  15. 替换节点
  16. replaceChild()

写一个格式化时间的方法

  1. function dateToString(date, format = 'yyyy-MM-dd') {
  2. const d = new Date(date);
  3. let result = format;
  4. const _config = {
  5. 'y+': d.getFullYear(),
  6. 'M+': d.getMonth() + 1, // 月
  7. 'd+': d.getDate(), // 日
  8. 'h+': d.getHours(), // 小时
  9. 'm+': d.getMinutes(), // 分
  10. 's+': d.getSeconds(), // 秒
  11. };
  12. for (const reg in _config) {
  13. if (!(new RegExp(`(${reg})`).test(result))) continue;
  14. const match = RegExp.$1;
  15. let num = `${_config[reg]}`;
  16. while (num.length < match.length) { num = `0${num}` }
  17. result = result.replace(match, num);
  18. }
  19. return result;
  20. }
  21. function stringToDate(str, format = 'yyyy-MM-dd') {
  22. let args = [/y+/, /M+/, /d+/, /h+/, /m+/, /s+/];
  23. args = args.reduce((re, reg, index) => {
  24. const match = format.match(reg);
  25. const defaultValue = [1970, 0, 1, 0, 0, 0][index];
  26. if (!match) return re.concat([defaultValue]);
  27. var index = match.index;
  28. const num = Number(str.slice(index).match(/\d+/));
  29. return re.concat([num]);
  30. }, []);
  31. args.unshift(null);
  32. return new(Date.bind.apply(Date, args));
  33. }

pjax和ajax的区别是什么? 

  1. pjax 是一个 jQuery 插件,它通过 ajaxpushState 技术提供了极速的(无刷新 ajax 加载)浏览体验,并且保持了真实的地址、网页标题,浏览器的后退(前进)按钮也可以正常使用。
  2. pjax 的工作原理是通过 ajax 从服务器端获取 HTML,在页面中用获取到的 HTML 替换指定容器元素中的内容。然后使用 pushState 技术更新浏览器地址栏中的当前地址。以下两点原因决定了 pjax 会有更快的浏览体验:
  3. 不存在页面资源(js/css)的重复加载和应用;
  4. 如果服务器端配置了 pjax,它可以只渲染页面局部内容,从而避免服务器渲染完整布局的额外开销。

微信小程序实现轨迹回放,微信原生小程序,基于uniapp的小程序?

需要写出轨迹拖动,进度条,开始,暂停,结束功能。

异步请求重试策略有哪些呢?

重试次数、重试时间间隔等

 写一个方法实现promise失败后自动重试

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge">
  7. <title>Document</title>
  8. </head>
  9. <body>
  10. </body>
  11. </html>
  12. <script>
  13. Promise.retry = (fun, limit = 5) => {
  14. return new Promise((resolve, reject) => {
  15. let __num = 1;
  16. let __run = () => {
  17. fun()
  18. .then(res => {
  19. resolve(res);
  20. })
  21. .catch(err => {
  22. if (__num++ >= limit) {
  23. reject(err)
  24. } else {
  25. console.log('retry again!!')
  26. __run()
  27. }
  28. })
  29. }
  30. __run()
  31. })
  32. }
  33. let k = 0
  34. function test() {
  35. return new Promise((resolve, reject) => {
  36. if (++k >= 3) {
  37. resolve(k)
  38. } else {
  39. reject('hhh')
  40. }
  41. })
  42. }
  43. Promise.retry(test).then(res => {
  44. console.log('resolve: ', res)
  45. }).catch(err => {
  46. console.log('reject: ', err)
  47. })
  48. // retry again!!
  49. // retry again!!
  50. // resolve: 3
  51. </script>

 运行结果
在这里插入图片描述

实现多张图片合成一张的效果 

  1. 原理是使用canvas画布。
  2. 在页面加载前 mounted方法里:
  3. setTimeout(() => {
  4. this.changeimg();
  5. }, 1000);
  6. changeimg( )方法:
  7. changeimg(){
  8. var self = this;
  9. var imgsrcArray = [
  10. require('../../assets/image/income/background.png'),
  11. $('#qrcode canvas')[0].toDataURL('image/png')
  12. ];
  13. var canvas = document.createElement('canvas');
  14. var ctx = canvas.getContext('2d');
  15. canvas.width = 750;
  16. canvas.height = 1334;
  17. var imglen = imgsrcArray.length;
  18. var showContent = '我是'+this.showPhone;
  19. var drawimg = (function f(n){
  20. if(n < imglen){
  21. var img = new Image();
  22. img.crossOrigin = 'Anonymous'; //解决跨域问题
  23. img.onload = function(){
  24. if(n == 0){
  25. ctx.drawImage(img,0,0,750,1334);
  26. ctx.font = '30px Adobe Ming Std';
  27. ctx.fillText(showContent,250,800);
  28. ctx.fillText('文字文字',250,850);
  29. }else{
  30. ctx.drawImage(img,250,900,250,250);
  31. }
  32. f(n+1);
  33. }
  34. img.src = imgsrcArray[n];
  35. }else{
  36. self.downloadUrl = canvas.toDataURL("image/jpeg");
  37. self.downloadUrl = self.downloadUrl.replace("data:image/jpeg;base64,", "");
  38. }
  39. })(0);
  40. }
  41. 本例中将一张背景图与二维码图合成一张图片 ,
  42. 二维码的生成也需要在此方法之前。
  43. html:
  44. <img style="width:100%;" :src="'data:image/jpeg;base64,' + downloadUrl" alt="">
  45. <div style="opacity:0;position:absolute;bottom:0;" id="qrcode"></div>

ajax如何接收后台传来的图片?

1.设置responseType为 Blob2.Blob保存为文件

 js源代码压缩都有哪些方法?它们的压缩原理分别是什么

  1. 方法
  2. 1.在线工具
  3. 2.webpack
  4. 原理
  5. 1.删除注释
  6. 2.变量名方法名字符精减

不用 + eval Function 实现加法
 

  1. // 使用位运算符实现
  2. function add (a, b) {
  3.     if (a == 0 || b == 0) {
  4.         return a || b;
  5.     }
  6.     while (b != 0) {
  7.         let i = b;
  8.         b = (a & b) << 1;
  9.         a = a ^ i;
  10.     }
  11.     return a;
  12. };

 写一个 document.querySelector 的逆方法

  1. document.queryNode = function(node){
  2.     if(node.id){
  3.         return '#'+ node.id;
  4.     }
  5.     if(node.className){
  6.         return '.'+ node.id;
  7.     }
  8.     return node.nodeName
  9. };

如何判断对象是否属于某个类?

  1. obj.proto === class.prototype 可以递归去找
  2. obj instanceof class

说说你对js沙箱的理解,它有什么应用场景?

在微前端有用到js沙箱,例如qiankun框架,主应用的js运行和子任务的js运行不会相互影响,是使用es6的proxy来实现的

纯函数和函数式编程有什么关系?

  1. 函数式编程是一种编程思想,纯函数是这种思想的基本
  2. 要实现函数式编程,我们所封装的方法应该是抽象的,应该是和外部状态无关系的,也就需要是纯函数的,这样才能保证抽象的方法可复用而且输出结果只决定于输入参数。

为什么要用纯函数? 

  1. 在此之前要先了解什么是纯函数,简单来说纯函数的定义有两个:
  2. 1.返回的结果只依赖于传入的参数。
  3. 2.执行过程中不产生副作用。
  4. 在这里就需要了解到什么是副作用
  5. 1.改变了外部变量或者对象属性
  6. 2.触发任何外部进程
  7. 3.发送http请求
  8. 4.调用其他有副作用的函数
  9. 5.……
  10. 那么我们为什么要用纯函数呢,从定义来看,我们可以知道纯函数不管你在什么时候请求它,只要参数是一样的,那返回的结果就肯定是一样的。
  11. 然后对于副作用我的理解是一个函数的功能要单一 ,你不能即在负责计算或者什么别的行为的同时还负责http请求什么的,发起http请求应该让另外一个函数去单独实现。
  12. 然后另外一个函数虽然产生了副作用,但是它的返回结果只依赖于传入的参数(比如链接)。这样做的好处有方便测试和后期维护,如何你一个函数负责多个功能,那后面估计看着这个函数都很难受。

使用js实现一个图片剪裁的功能

  1. /**
  2. * 裁切图片
  3. * @param imgUrl 原始图片路径
  4. * @param x,y,width,height 从点[x, y]开始,将宽度width,高度height的区域裁切下来
  5. * tips:需要运行于服务器环境下切图片为同域
  6. */
  7. function clipImage(imgUrl, x, y, width, height) {
  8. return new Promise((resolve, reject) => {
  9. let cvs = document.createElement("canvas");
  10. cvs.width = width;
  11. cvs.height = height;
  12. var ctx = cvs.getContext('2d');
  13. let _img = new Image();
  14. _img.src = imgUrl;
  15. _img.onload = () => {
  16. ctx.drawImage(_img, 0 - x, 0 - y);
  17. resolve(cvs.toDataURL());
  18. }
  19. })
  20. }
  21. clipImage("./img/loginbg.jpg", 100, 100, 300, 400).then(res => {
  22. let __img = document.createElement("img");
  23. __img.src = res;
  24. document.body.appendChild(__img);
  25. })

使用for-in语句能保证遍历对象的顺序吗?如果不能那为什么?如果可以那又如何保证? 

  1. Chrome Opera 的 JavaScript 解析引擎遵循的是新版 ECMA-262 第五版规范。因此,使用 for-in 语句遍历对象属性时遍历顺序并非属性构建顺序。而 IE6 IE7 IE8 Firefox Safari 的 JavaScript 解析引擎遵循的是较老的 ECMA-262 第三版规范,属性遍历顺序由属性构建的顺序决定。
  2. 如果我们需要按照一定的顺序输出属性,也可以先在一个数组中保存所有的key值,再将数组排序,最后循环这个key数组,通过key获取对象中的属性即可:
  3. var user = {};
  4. if(!user['Jason']) {
  5. user['Jason'] = [];
  6. }
  7. user['Jason']['grade'] = 3;
  8. user['Jason']['level'] = 1;
  9. if(!user['arthinking']) {
  10. user['arthinking'] = [];
  11. }
  12. user['arthinking']['grade'] = 4;
  13. user['arthinking']['level'] = 1;
  14. console.log(user);
  15. for(var key in user){
  16. console.log('key: ', key);
  17. }
  18. var keys = [];
  19. for(var key in user){
  20. keys.push(key);
  21. }
  22. keys = keys.sort();
  23. for(var i=0; i<keys.length; i++){
  24. var key = keys[i];
  25. console.log(user[key]['grade']);
  26. }

写个方法获取屏幕的DPI 

  1. (function() {
  2. var arrDPI = new Array();
  3. if ( window.screen.deviceXDPI) {
  4. arrDPI[0] = window.screen.deviceXDPI;
  5. arrDPI[1] = window.screen.deviceYDPI;
  6. }
  7. else {
  8. var tmpNode = document.createElement( "DIV" );
  9. tmpNode.style.cssText = "width:1in;height:1in;position:absolute;left:0px;top:0px;z-index:99;visibility:hidden";
  10. document.body.appendChild( tmpNode );
  11. arrDPI[0] = parseInt( tmpNode.offsetWidth );
  12. arrDPI[1] = parseInt( tmpNode.offsetHeight );
  13. tmpNode.parentNode.removeChild( tmpNode );
  14. }
  15. console.dir(arrDPI);
  16. return arrDPI;
  17. })()

promise的构造函数是同步执行还是异步执行,它的then方法呢?

promise构造函数是同步执行的,then方法是异步执行的。

内存泄漏和内存溢出有什么区别

  1. 内存泄露:用动态储存分配函数内存空间,在使用完毕后未释放,导致一直占据该内存单元,直到程序结束。
  2. 内存溢出:不顾堆栈分配的局部数据块大小,向数据块中写入过多数据,导致数据越界,结果覆盖了别的数据。常在递归中发生。

 写一个方法把科学计数法转换成数字或者字符串

  1. function c(a) {
  2. return a.replace(/^(\d+)(?:.(\d+))*eE(\d+)/,(_,a,a1,p,n)=>{
  3. a1=a1||''
  4. if(p==='-'&&n>0) {
  5. return '0.'+'0'.repeat(n-1)+a+a1
  6. }else{
  7. return a+(a1.length>n? a1.substr(0, n)+'.'+a1.substr(n): a1+'0'.repeat(n-a1.length))
  8. }
  9. })
  10. }

写一个方法,实时验证input输入的值是否满足金额如:3.56(最多只有两位小数且只能数字和小数点)的格式,其它特殊字符禁止输入

  1. <body>
  2. <input type="text" id="amount">
  3. <em id="message"></em>
  4. </body>
  5. <script>
  6. const amountInput = document.getElementById('amount');
  7. const msg = document.querySelector('#message');
  8. amountInput.oninput = function (event) {
  9. let value = event.target.value;
  10. let pat = /^\d+(\.\d{1,2})?$/;
  11. msg.innerHTML = pat.test(value) ? 'True' : 'False';
  12. }
  13. </script>
  14. 更优方式---input的 pattern属性
  15. <input type="text" pattern="^\d+(\.\d{1,2})?$">

使用delete删除数组,其长度会改变吗 

  1. 使用delete删除数组元素,其长度会改变吗?
  2. 咱来写个案例
    声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Gausst松鼠会/article/detail/391932
    推荐阅读
    相关标签