前端逻辑练习题+学习记录 不定期更新

编程题

1.返回数组中最大的数字(reduce函数)

  • largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);
  • 返回结果:[5,27,39,1001]
reduce函数参考链接:https://www.jianshu.com/p/e375ba1cfc47
function largestOfFour(arr) {
		let num = [] 
		let list = arr.map(item => {
			num.push(item.reduce(function (x, y) {
				return Math.max(x, y) // 返回一个数组中最大的数值
			}))
		})
		return num  // [5,27,39,1001]
	}
	//reduce() 方法接收一个函数作为累加器,数组中的每个值(从左到右)开始计算,参数2继承上一个计算的值,最终计算为一个值。
largestOfFour([[4, 5, 1, 3], [13, 27, 18, 26], [32, 35, 37, 39], [1000, 1001, 857, 1]]);	

2.查找字符串中最长的单词

  • findLongestWordLength(“The quick brown fox jumped over the lazy dog”);
  • 返回结果:6
function findLongestWordLength(str) {
// str.split(" ")  ["The", "quick", "brown", "fox", "jumped", "over", "the", "lazy", "dog"]
  return Math.max(...str.split(" ").map(word=>word.length))
}
findLongestWordLength("The quick brown fox jumped over the lazy dog");

3.检查字符串的结尾

  • confirmEnding(“Bastian”, “n”); 结尾是否为n 为n返回true 参数二字符串长度不限
一丶
function confirmEnding(str, target) {
 return str.slice(str.length-target.length)===target
}
二丶
return str.endsWith(target) // js内置方法检查后缀
confirmEnding("Bastian", "n");

4.重复字符串

  • repeatStringNumTimes(“abc”, 3); 返回abcabcabc
function repeatStringNumTimes(str, num) {
  var accumulatedStr = "";
  while (num > 0) {
    accumulatedStr += str;
    num--;
  }// 重复执行直到不满足条件
  return accumulatedStr;
}
repeatStringNumTimes("abc", 3); 

(2).
function repeatStringNumTimes(str, num) {
  return num > 0 ? str.repeat(num) : "";
}//使用repeat之后会将原来的字符串复制n次

repeatStringNumTimes("abc", 3);

5.单词的首字母大写

  • titleCase(“I’m a little tea pot”)
  • 结果: I’m A Little Tea Pot
	function titleCase(str) {
		let list = str.toLowerCase().split(" ") // ["i'm", "a", "little", "tea", "pot"] 全部转换为小写
		list = list.map(x => {return x.replace(x[0], x[0].toUpperCase())})
		//替换数组中的每个字符串下标为0的为大写 map不改变原来的数组,需拿变量接收
		return list.join(" ") //进行拼接
	}

	titleCase("I'm a little tea pot");

6.递归的简单应用

  • let moneye = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13,], [14]]], 10]

  • 结果:let list=[1,2,2,3,4,5,5,6,7,8,9,11,12,12,13,14,10]

let list = []
let moneye = [[1, 2, 2], [3, 4, 5, 5], [6, 7, 8, 9, [11, 12, [12, 13,], [14]]], 10]
data(moneye, list)
function data(moneye, list) {
   for(let i in moneye){
   // 判断数组是否还有子集,如果没有子集就push到新数组,如果还有则递归参数为子集
        typeof moneye[i] =="object"?data(moneye[i],list):list.push(moneye[i])
   }
}

7.请不要重复

  • aab应该返回长度2, 因为它总共有 6 种排列方式: aab, aab, aba, aba, baa, baa,但是其中只有 2 个没有连续重复的字符(字符 a 是本例中的重复字符):aba,aba
    function permAlone(str) {
        let perms = []  
        // form:后两位  newly:开头字符串
        function dig(form, newly) {
            if (newly.length == str.length) {//如果长度相等则退出递归 push新数组
                perms.push(newly)
            } else {
                for (let i = 0; i < form.length; i++) {
                    let list = []
                    for (let k = 0; k < form.length; k++) {
                        if (i != k) { //排除冲突 form[i] 作为排列开头文字  form[k]则是排列后两位
                            list.push(form[k])
                        }
                    }
                    dig(list, newly + form[i])
                }
            }
        }
        dig(str, "")
         console.log(perms) // aab, aab, aba, aba, baa, baa
        let a = perms.filter(item => {
            return !item.match(/(.)\1+/)
        })  // 过滤掉不符合条件的参数  aba,aba
        return a.length
    }
    permAlone('aab');

8.找出两个数组相同的参数

  • let list=[1, 2, 3], [4, 3, 2]

  • 结果:[2, 3]

const intersection = (a, b) => {
  const s = new Set(b);  // set方法
  return a.filter(x => s.has(x)); // 判断b中是否有a相同的数值 然后进行过滤处理
};

intersection([1, 2, 3], [4, 3, 2]); // [2, 3]

9.修改以下 print 函数,使之输出 0 到 99,或者 99 到 0

要求:
1、只能修改 setTimeout 到 Math.floor(Math.random() * 1000 的代码
2、不能修改 Math.floor(Math.random() * 1000
3、不能使用全局变量
题目外链:https://github.com/sisterAn/JavaScript-Algorithms/issues/101
function print(n){
  setTimeout(() => {
    console.log(n);
  }, Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
题解:
方法一:
function print(n){
  setTimeout((() => {
    console.log(n);
  })(), Math.floor(Math.random() * 1000));
}
for(var i = 0; i < 100; i++){
  print(i);
}
方法二:
function print(n){
  setTimeout(async () => {
    await console.log(n);
  }), Math.floor(Math.random() * 1000);
}
for(var i = 0; i < 100; i++){
  print(i);
}
//settimeout宏任务,await 微任务
//同步的跑完会放100个宏任务到宏任务栈 然后执行宏任务发现里面是微任务先跑微任务

10, 实现一个add方法,使计算结果能够满足如下预期:(柯里化函数)

  add(1)(2)(3)    // 6;
  add(1, 2, 3)(4)    //10;
  add(1)(2)(3)(4)(5)    //15;
题解:
柯里化参考链接:https://www.jianshu.com/p/5e1899fe7d6b
题目参考链接:https://github.com/sisterAn/JavaScript-Algorithms/issues/103
简化版:
let add=function(...args){
  let foo=function(...newArgs){
    return add(...[...args,...newArgs])
  }
  foo.toString=function(){
    return args.reduce((a,b)=>a+b)
  }
  foo.sum=function(){
    return foo.toString()
  }
  return foo
}
优化版:
let add = (...args)=>{
	let foo =(...newArgs)=> add(...[...args,...newArgs])
	foo.sum=()=> args.reduce((a,b)=>a+b)
	return foo 
}
console.log(add(1).sum())  //1
console.log(add(1)(2).sum()) //3
console.log(add(1)(2)(3).sum()) //6
//add(1)返回的就是foo函数,再次执行(2),此时才是执行foo,所以是2,
// 隐式转换会触发 toString()

11.判断给定一个只包括 ‘(’ ,’)’ ,’{’ ,’}’ ,’[’ ,’]’ 的字符串,判断字符串是否有效。`

题目链接:https://github.com/sisterAn/JavaScript-Algorithms/issues/25
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
3.注意空字符串可被认为是有效字符串。
示例 1:
输入: "()"
输出: true
示例 4:
输入: "([)]"
输出: false
示例 5:
输入: "{[]}"
输出: true

12.输入: [1,2,3]

输出:[[1,2,3],[1,3,2],[2,1,3],[2,3,1], [3,1,2],[3,2,1]]
题目链接:https://github.com/sisterAn/JavaScript-Algorithms/issues/102

12.平均分配

需要分配的数量  
let num={name:'num',num:5};
需要分配的人员
let list=[
		  {name:'a',num:32},
          {name:'b',num:3},
          {name:'c',num:1}
         ]
输出:
	     [
		  {name:'a',num:32},
		  {name:'b',num:5},
		  {name:'c',num:4}
		 ]
let num={name:'num',num:5};
let list=[
     {name:'a',num:32},
     {name:'b',num:3},
     {name:'c',num:1}   
 ];
 let type=Number.MAX_SAFE_INTEGER; // 无穷大
 let typeIndex=null; // 分配下标
 for(let i=0;i<num.num;i++){
   type=Number.MAX_SAFE_INTEGER;
   list.map((x,index)=>{
     if(x.num<type){
       type=x.num
       typeIndex=index
     }}) // 找出最小的数
     // 防止数量一致
    let isPush= list.filter(x=>x.num==type)
    if(isPush.length>1){
     list[typeIndex].num++
      continue
    }
    // 添加数量
    list.map(x=>{ if(x.num==type)x.num++})
 }

学习日常

此代码段将获取数组对象属性的平均值(写法思路)

function averageBy(arr,fu){
      console.log(arr) // [1,2,3,4,5]
      console.log(fu) // o => o.n
      console.log(typeof fu) // function
      arr.map(typeof fu === 'function' ? fu : val => val[fu]).reduce((acc, val) => acc + val, 0)
      return arr.length
    }
    //typeof fu === 'function' ? fu : val => val[fu] 
    // 这一段代码的逻辑是判断参数2的类型
    averageBy([1,2,3,4,5],o => o.n)  //5
    averageBy([1,2,3,4,5],"n")  //5

deepFlatten:递归扁平化数组

const deepFlatten = arr => [].concat(...arr.map(v => (Array.isArray(v) ? deepFlatten(v) : v)));
// concat()连接两个或多个数组
// 创建一个[ ]数组进行连接  遍历循环传递参数,  判断是否是数组 如果是则递归 如果不是则返回进行连接
deepFlatten([1, [2], [[3], 4], 5]); // [1,2,3,4,5]

开发过程中的小细节

1.vue中的路由跳转:
 this.$router.push({name: `xxx`,query: { xxx: xxx}// 参数});

2.使用计算属性监听vuex状态参数,可用于不同页面的监听(:公告管理/购物车);
//利用计算属性  
  computed: {
    // 未读信息
    afficheNum() {
      return this.$store.state.app.unreadNum;
    },
    // 删除
    afficheDelete(){
      return this.$store.state.app.unreadDelete;
    }
  },
  //监听执行
  watch: {
    afficheNum(val) {
      this.myNoticeTopArea()
    },
    afficheDelete(val) {
      this.myNoticeTopArea()
    },
  },
  
3.改变原生滚动条;
 -ms-overflow-style: none;
 overflow: -moz-scrollbars-none;
 /*隐藏滚动条,当IE下溢出,仍然可以滚动*/
  -ms-overflow-style: scrollbar;
  scrollbar-arrow-color: $whilt;
  scrollbar-face-color: rgb(224, 224, 224);
  scrollbar-3dlight-color: $whilt;
  scrollbar-highlight-color: $whilt;
  scrollbar-shadow-color: $whilt;
  scrollbar-darkshadow-color: $whilt;
  scrollbar-track-color: $whilt;
  scrollbar-base-color: $whilt;
  ::-webkit-scrollbar

4.call,apply等都不能改变箭头函数的指向;

5.解决 vue 项目运行过程报错 JavaScript heap out of memory(内存溢出)
	https://blog.csdn.net/lucky_zeng/article/details/108622002	
	
6.关于replace全部替换;
示例1:
	 var resultMore=test.replace(/123/g,'8');	
示例2:
	 var ch = "/";
	 var str = "这是一/个变量,这是一个变量";
	 var val = str .replace(new RegExp(ch,'g'),"b");

7.当有相同的类,可以根据value进行区分
<button class="script" value="sub" ></button>
<button class="script" value="super" data-value='super'></button>
document.querySelector(".script[value='sub']")
document.querySelector(".script[value='super']")
自定义属性同理
document.querySelector(".script[data-value='super']")

8.标签中的title可以运用于鼠标悬浮文字提示

9.数组之间的变异(会改变被这些方法调用的原始数组)和非变异(不会改变被这些方法调用的原始数组)
变异:push()和pop(),shift()unshift(),sort(),splice()
非变异:join(),concat(),slice(),indexOf()lastIndexOf()ES5新增),forEach()ES5新增),some()ES5新增),fliter() (ES5新增),map()ES5新增),every()ES5新增),reduce()reduceRight()ES5新增)

flatten:指定深度扁平化数组

const flatten = (arr, depth = 1) =>
  arr.reduce((a, v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
  
flatten([1, [2], 3, 4]); // [1, 2, 3, 4]
flatten([1, [2, [3, [4, 5], 6], 7], 8], 2); // [1, 2, 3, [4, 5], 6, 7, 8]

解构赋值

<--互换位置-->
let a=8 let b=7
[a,b]=[b,a]
console.log(b)//8
console.log(a)//7

<--将数组分别赋值不同的变量-->
const source = [1,2,3,4,5,6,7,8,9,10];
function removeFirstTwo(list) {
  let  [a,b,...arr]=list;
  console.log(a) // 1
  console.log(b) // 2
  return arr;
}
const arr = removeFirstTwo(source);
console.log(arr); //  [3,4,5,6,7,8,9,10]
console.log(source); //  [1,2,3,4,5,6,7,8,9,10];

<--对象中的对象-->
let obj={
	objCS:{max:89}
}
function objfc(obj){
	let {objCS:{max:nextObj}}=obj
	return nextObj // 89
}
<--将对象作为函数的参数传递-->
修改前:
const profileUpdate = (profileData) => {
  const { name, age, nationality, location } = profileData;
} 
修改后:
const profileUpdate = ({ name, age, nationality, location }) => {
}

Class

修改前:
var SpaceShuttle = function(targetPlanet){
  this.targetPlanet = targetPlanet;
}
var zeus = new SpaceShuttle('Jupiter');

修改后:
class SpaceShuttle {
  constructor(targetPlanet){
    this.targetPlanet = targetPlanet;
  }
}
const zeus = new SpaceShuttle('Jupiter');

关于 工厂函数 的举例

function httpClientFactory(baseUrl) {
  return {
    baseUrl: baseUrl,
    listUsers: () => {
      return axios.get(`${baseUrl}/users`)
    },
    getUser: (id) => {
      return axios.get(`${baseUrl}/users/${id}`)
    },
    getBook: (bookName) => {
      return axios.get(`${baseUrl}/books/${bookName}`)
    }
  }
}

const httpClient = httpClientFactory("https://your-endpoints/api");
httpClient.getUser("123");
httpClient.getBook("JavaScript Is Interesting");
console.log("The httpClient's baseUrl is " + httpClient.baseUrl);
<--工厂函数对比类-->
class HttpClient {
  constructor(baseUrl) {
    this.baseUrl = baseUrl;
    this.listUsers = this.listUsers.bind(this);
    this.getUser = this.getUser.bind(this);
    this.getBook = this.listUsers.bind(this);
  }
  listUsers() {
    return axios.get(`${this.baseUrl}/users`)
  }
  getUser(id) {
    return axios.get(`${this.baseUrl}/users/${id}`)
  }
  getBook(bookName) {
    return axios.get(`${this.baseUrl}/books/${bookName}`)
  }
}

const httpClient = new HttpClient("https://your-endpoints/api");
httpClient.getUser("123");
httpClient.getBook("JavaScript Is Interesting");
console.log("The httpClient's baseUrl is " + httpClient.baseUrl);

Object.entries() Object.values()

const credits = {
  producer: '大迁世界',
  name: '前端小智',
  rating: 9
}
const arr = Object.entries(credits) // [ [ 'producer', '大迁世界' ], [ 'name', '前端小智' ], [ 'rating', 9 ] ]
const obj= Object.values(credits) // [ '大迁世界', '前端小智', 9 ]

~~

let val = '123.95'
console.log(Math.floor(val)) // 123 常规写法 
console.log(~~val) // 123 简写

vue中 vue.set()的用法

//Vue内部,数据响应是通过使用Object.definePrototype监听对象的每一个键的getter,setter方法来实现的,
//但通过这种方法只能监听到已有属性,新增的属性是无法监听到的
data() {
    return {
      userInfo: {
        name: '子君',
        sex: '男',
        // 我先提前定义好
        officialAccount: ''
      }
    }
  }
方法一:
this.userInfo = {
  // 将原来的userInfo 通过扩展运算法复制到新的对象里面
  ...this.userInfo,
  // 添加新属性
  officialAccount: '前端有的玩'
}
方法二:
import Vue from 'vue'
handleAddOfficialAccount() {
//Vue.set( target, propertyName, value )
/**
* target 要修改的对象
* prpertyName 要添加的属性名称
* value 要添加的属性值
*/

  Vue.set(this.userInfo,'officialAccount', '前端有的玩')
}
//但是每次要用到set方法的时候,还要把Vue引入进来
//Vue又将set方法挂载到了Vue的原型链上了
//即Vue.prototype.$set = Vue.set,所以在Vue组件内部可以直接使用this.$set代替Vue.set
this.$set(this.userInfo,'officialAccount', '前端有的玩')
// 数组可以这样写  数组中push,pop,shift,unshift,splice,sort,reverse是会数据响应
// 但是this.list[0] = '王五'是没有用的
Vue.$set(this.list,0,'王五')

事件循环

一、同步和异步
1.所谓单线程,无非就是同步队列和异步队列,js代码是自上向下执行的,
2.在主线程中立即执行的就是同步任务,比如简单的逻辑操作及函数,而异步任务不会立马立马执行
3.会挪步放到到异步队列中,比如ajax、promise、事件、计时器等等。
4.也就是先执行同步,主线程结束后再按照异步的顺序再次执行。

二.微观任务和宏观任务(先执行微观任务,再执行宏观任务)
1.微观任务主要包括:Promise、MutaionObserver、process.nextTick(Node.js 环境)
2.宏观任务主要包含:setTimeout、setInterval、script(整体代码)I/OUI 交互事件、setImmediate(Node.js 环境)

规范:先执行微观任务,再执行宏观任务
console.log('开始111');
setTimeout(function() {
   console.log('setTimeout111');
}, 0);
Promise.resolve().then(function() {
   console.log('promise111');
}).then(function() {
   console.log('promise222');
});
console.log('开始222');

// 开始111 、开始222 、 promise111 、 promise222 、 setTimeout111 
1、遇到同步任务,直接先打印 “开始111”。
2、遇到异步 setTimeout ,先放到队列中等待执行。
3、遇到了 Promise ,放到等待队列中。
4、遇到同步任务,直接打印 “开始222”。
5、同步执行完,返回执行队列中的代码,从上往下执行,发现有宏观任务 setTimeout 和微观任务 Promise ,那么先执行微观任务,再执行宏观任务
------------------------------------------------------------------------------

console.log('开始111');
setTimeout(function () {
   console.log('timeout111');
});
new Promise(resolve => {
   console.log('promise111');
   resolve();
   setTimeout(() => console.log('timeout222'));
}).then(function () {
   console.log('promise222')
})
console.log('开始222');

//开始111 、 promise111 、 开始222 、 promise222 、 timeout111 、 timeout222
1、遇到同步代码,先打印 “开始111” 。
2、遇到setTimeout异步,放入队列,等待执行 。
3、中途遇到Promise函数,函数直接执行,打印 “promise111”。
4、遇到setTimeout ,属于异步,放入队列,等待执行。
5、遇到Promise的then等待成功返回,异步,放入队列。
6、遇到同步,打印 “开始222”。
7、执行完,返回,将异步队列中的代码,按顺序执行。有一个微观任务,then后的,所以打印 “promise222”,再执行两个宏观任务 “timeout111” “timeout222”。

防抖与节流

参考链接:
节流:https://github.com/sisterAn/JavaScript-Algorithms/issues/92
防抖:https://github.com/sisterAn/JavaScript-Algorithms/issues/95
实现方案有以下两种:

节流:
第一种:
  用时间戳来判断是否已到执行时间,记录上次执行的时间戳,
  然后每次触发事件执行回调,回调中判断当前时间戳距离上次执行时间戳的间隔是否已经达到时间差(Xms) ,如果是则执行,并更新上次执行的时间戳,如此循环。
第二种
  使用定时器,比如当 scroll 事件刚触发时,打印一个 hello world
  然后设置个 1000ms 的定时器,此后每次触发 scroll 事件触发回调
  如果已经存在定时器,则回调不执行方法,直到定时器触发
  handler 被清除,然后重新设置定时器。

在jquery 中动态添加 !important 样式

$(".el-table__row.current-row a").css("cssText","color:red!important")

回调函数

// 如果需要获取一个函数中异步操作的结果,则必须通过回调函数来获取
function getAmie(callback){
   let temp = Math.random();
    setTimeout(() => {
        callback(temp);
    }, 1000);
}
getAmie((temp) => {})) // 这里的temp就是获取的Math.random()

// 关于回调的用法
let arr=[1,2,3]
function cs(item,callback){
   console.lot(item) // [1,2,3]
   console.log(callback) // ƒ (item){console.log(item,"我是回调")}
   item[0]=3
    if(typeof callback === "function"){
       callback(item)
    }
}
cs(arr,function(item){
  console.log(item,"我是回调") // [3,2,3]
})

函数提升

var foo =function(x, y){
   return x - y;
}
function foo(x, y){
   return x + y;
}
var num = foo(1, 2);
//variable hoisting变量提升
var foo;//foo#1
var num;
//function declaration hoisting函数声明提升
function foo(x, y){//foo#2
   return x + y;
}
//function expression NOT hoisted函数表达式不会被提升
foo =function(x, y){//foo#3
   return x - y;
}
num = foo(1, 2);//这里使用foo#3
规则
1. 变量声明、函数声明都会被提升到作用域顶处;
2.变量提升只会提升变量名的声明,而不会提升变量的赋值初始化。
3.函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上。

promise

// 链接:https://juejin.im/post/6844903607968481287
1.基础用法
var test = new Promise((resolve,reject)=>{
   resolve();
});

test.then(data => {
    console.log('promise first then : ', data);
    return Promise.resolve(4444);     // return是resolve则是下一个then的形参
  })
  .then(data => {
    console.log('get parent(p1) resolve data : ', data);
  })
  console.log("1")
// 1
// promise first then : undefing
// get parent(p1) resolve data 4444

2.all的用法
场景:可以并行执行多个异步操作,并且在一个回调中处理所有的返回数据,有一个场景是很适合用这个的,
一些游戏类的素材比较多的应用,打开网页时,预先加载需要用到的各种资源如图片、flash以及各种静态文件。
所有的都加载完后,我们再进行页面的初始化。
let Promise1 = new Promise(function(resolve, reject){})
let Promise2 = new Promise(function(resolve, reject){})
let Promise3 = new Promise(function(resolve, reject){})
let p = Promise.all([Promise1, Promise2, Promise3])
p.then(funciton(){
  // 三个都成功则成功  
}, function(){
  // 只要有失败,则失败 
})


3.race的用法
场景:requestImg函数会异步请求一张图片,我把地址写为"图片的路径",所以肯定是无法成功请求到的。timeout函数是一个延时5秒的异步操作。
我们把这两个返回Promise对象的函数放进race,于是他俩就会赛跑,如果5秒之内图片请求成功了,那么遍进入then方法,执行正常的流程。
如果5秒钟图片还未成功返回,那么timeout就跑赢了,则进入catch,报出“图片请求超时”的信息。
 //请求某个图片资源
    function requestImg(){
        var p = new Promise((resolve, reject) => {
            var img = new Image();
            img.onload = function(){
                resolve(img);
            }
            img.src = '图片的路径';
        });
        return p;
    }
    //延时函数,用于给请求计时
    function timeout(){
        var p = new Promise((resolve, reject) => {
            setTimeout(() => {
                reject('图片请求超时');
            }, 5000);
        });
        return p;
    }
    Promise.race([requestImg(), timeout()]).then((data) =>{
        console.log(data);
    }).catch((err) => {
        console.log(err);
    });

async/await

参考链接:
https://www.cnblogs.com/jsgoshu/p/11444404.html
https://mp.weixin.qq.com/s/MoaqqcOwR5PYDWWEOO1X6A
https://mp.weixin.qq.com/s/EmIwV-pUAXBdOa-lMT7DZg
function asyncFn () {
  return new Promise(function (resolve, reject) {
  		console.log("cs1")
        resolve('resolve')
  })
}
var value1 = await asyncFn() 
console.log(value1+"1")
var value2 = value1+"2"
console.log(value1)
console.log(value2)
// 依次打印  cs1,resolve1,resolve,resolve2
如果promise对象的结果是resolve,它会将resolve的值,作为await表达式的运算结果。

项目中用法:
在这里插入图片描述

Object.assign

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);
console.log(target);
// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);
// expected output: Object { a: 1, b: 4, c: 5 }

html自定义属性data

<li
  data-url="测试url"
  data-title="测试标题"
  data-cs="测试"
 ></li>
 list.addEventListener("click", function () {
    let url = this.dataset.url; //测试url
    let title = this.dataset.title; //测试标题
  });

map和forEach的区别

相同点都是有三个参数:
1.当前元素的索引,2.调用的数组 3.执行callback函数时值被用作this

不同点:
map返回一个由原数组执行回调后的一个新数组
forEach没有返回值

map源码解析:
Array.prototype.ab = function(callback, thisArg) {
  console.log(callback)  // x=>{return x+1}
  console.log(thisArg) // undefing
  // 这里的this是[1,2,3] 因为是arr点出来的 所以this指向是他
  if (this == undefined) {
    throw new TypeError('this is null or not defined');
  }
  if (typeof callback !== 'function') {
    throw new TypeError(callback + ' is not a function');
  }
  const res = [];
  // 让O成为回调函数的对象传递(强制转换对象)
  const O = Object(this);
  // >>>0 保证len为number,且为正整数
  const len = O.length >>> 0;
  for (let i = 0; i < len; i++) {
    if (i in O) {
      // 调用回调函数并传入新数组 
      //call和apply的第一个参数是null/undefined时函数内的的this指向window或global 
      res[i] = callback.call(thisArg, O[i], i, this);
    }
  }
  return res;
}
let arr=[1,2,3]
arr=arr.ab(x=>{
   //  先执行ab()在callback.call(thisArg, O[i], i, this)的时候才会回到这里
  return x+1
}) 
console.log(arr) //[2,3,4]

需求问题

1. element表格实现自定义输入框在这里插入图片描述
直接在col中使用插槽即可,那插入组件后要怎么绑定各自的值呢,如果绑定一个data中的值肯定不行,那样的话,所有的行都绑定的是这个值,一输入的话全部都改动了。
其实要绑定各自的值也不难,方法还是插槽,我们在使用插槽插入组件时,会带出一个scope属性,这个scope属性中有表格的各种值,使用其中的row即可为每行组件绑定自己的值。例如:v-model=“scope.row.data”;

2.element表格错位问题,修改了element的滚动条宽度,导致的间隙问题
在这里插入图片描述

   body .el-table th.gutter{
      display: table-cell!important;
      width: 14px!important; // 修改的element滚动条宽度,设置成多少则多少,如无修改,不用理会
  }  // 解决element浮动错位问题
 // 因为修改了element的滚动条宽度,导致的间隙问题  
 // 当没有滚动条的时候 
  //.el-table__body-wrapper.is-scrolling-none~.el-table__fixed-right{
     //   right: 0px !important;
//   }
  // 当有竖向滚动条
  .el-table--scrollable-y .el-table__fixed-right{
        right: 13px !important;
    }
  // 当有横向滚动条
  .el-table--scrollable-x .el-table__fixed-right{
        height: calc(100% - 4.5px) !important;
   }
   // 浮动高度设置
   .el-table__fixed,
   .el-table__fixed-right {
         height: calc(100% + 5px) !important;
  }

3.动态添加标签
在这里插入图片描述
4.vue中mixins的使用
在这里插入图片描述

5,根据输入框内容,筛选选中的内容进行变色处理

 <span class="el-checkbox__label"
   v-html="brightenKeyword(country.fieldName,secvalue)"
></span>

   // 筛选变色
    brightenKeyword(val, keyword, status) {
      const Reg = new RegExp(keyword, "i");
      if (status == "1" && this.isAble == true) {
        var res = `<span class="isAbcolor">${keyword}</span>`;
      }
      if (val) {
        const res = val.replace(
          Reg,
          `<span ref="chooseDir" class="chooseDir" >${keyword}</span>`
        );
        return res;
      }
    },

32个手撕JS,彻底摆脱初级前端(面试高频)源码:https://mp.weixin.qq.com/s/tCGDM_EUOIWBPioz_wT3fQ

题目网站练习:https://learn.freecodecamp.one/

练习题大部分出自这里,做一个学习记录,不定时更新

es6语法:https://es6.ruanyifeng.com/#docs/let

JavaScript工具函数:https://mp.weixin.qq.com/s/I72GRE3PKvQf4R8yg-RmZQ

TS:https://www.jianshu.com/p/a540567ce1ce

41个最新的JavaScript开发技巧:https://mp.weixin.qq.com/s/QetU7iwwdeZKudhHdWIjjQ

基础篇:https://blog.poetries.top/FE-Interview-Questions/docs/base.html

异常监控系统:https://mp.weixin.qq.com/s/S7m8-ZQPNKfFHu0826CmZg

力扣算法:https://leetcode-cn.com/

牛客网https://www.nowcoder.com/

axios的封装:https://mp.weixin.qq.com/s/IKCSVS5BvvarzXZesOP-DQ

面试题:

-https://github.com/yisainan/web-interview/blob/master/README.md
-https://wangyaxing.cn/blog/interview/#javascript

Nginx:https://mp.weixin.qq.com/s/NFxAK9DM1-LV1p8dFXz1dA

懒加载原理:https://mp.weixin.qq.com/s/36oBZMd-m-2k5EKPghfG3A

flex布局:https://www.ruanyifeng.com/blog/2015/07/flex-grammar.html

富文本编辑器原理https://juejin.cn/post/6844903871110709256

免费的计算机书籍:https://github.com/ruanyf/free-books

css面试题

  • https://mp.weixin.qq.com/s/GuhHd6yW9GGWsN-Nbq9cBw
  • https://mp.weixin.qq.com/s/fgwHBsGWE-laAGO-eXcHvw
    以上都是学习过程中,发现的一些好网站.做收集处理,如有侵权,请联系我及时删除
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值