1.实现 (5).add(3).minus(2) //6
~(function (){
function check(n){
n=Number(n)
return isNaN(n)?0:n
}
function add(n){
n=check(n)
return this+n
}
function minus(n){
n=check(n)
return this-n
}
Number.prototype.add=add
Number.prototype.minus=minus
})()
2.箭头函数没有自己的this ,this指向当前函数执行的上下文,且无法用call apply bind 改变指向
function fn(){
console.log(this)
}
document.body.onclick=fn //this指向body
function fn(){
console.log(this)
}
document.body.onclick=fn.call(window) //call会不等点击就立即执行,this指向window
function fn(){
console.log(this)
}
document.body.onclick=fn.bind(window) //点击之后打印window
let fn=()=>{
console.log(this)
}
document.body.onclick=fn //点击后打印window而不是body而且不能用call和bind改变
let fn=()=>{
console.log(this)
}
document.body.onclick=fn.bind({}) //还是打印window 箭头函数this无法改变
3.箭头函数没有自己的arguments 可用(...arg) 代替
4.箭头函数不能作为构造函数 用new关键字执行 会报错(箭头函数没有 this,也没有prototype 属性,也没有自己的constructor构造函数)
5.正则匹配字符串中的字母,大写转小写 小写转大写,
let str='abcDE677#%yut987RFV'
str=str.replace(/[a-zA-Z]/g,(item)=>{
if(item.toUpperCase()===item){
return item.toLowerCase()
}else{
return item.toUpperCase()
}
})
//ABCde677#%YUT987rfv
/abc(?=8)/
let str='abc8lgknhl'
6,正则,必须包含大小写字母 数字的6-16位字符串
let reg=/(?!^[a-zA-Z]+$)(?!^[a-z0-9]+$)(?!^[A-Z0-9]+$)^[a-zA-Z0-9]{6,16}$/;
7.收集一个滚动列表插件
listMove(id, t = 2000) {
var $uList = $(id);
var timer = null;
//触摸清空定时器
$uList
.hover(
function () {
clearInterval(timer);
},
function () {
//离开启动定时器
timer = setInterval(function () {
scrollList($uList);
}, t);
}
)
.trigger("mouseleave"); //自动触发触摸事件
//滚动动画
function scrollList(obj) {
//获得当前<li>的高度
var scrollHeight = $(`${id} .item:first`).height();
//滚动出一个<li>的高度
$uList.stop().animate(
{
marginTop: -scrollHeight
},
700,
function () {
//动画结束后,将当前<ul>marginTop置为初始值0状态,再将第一个<li>拼接到末尾。
$uList
.css({
marginTop: 0
})
.find(".item:first")
.appendTo($uList);
}
);
}
}
挂载到vue原型上
export default {
install: function (vm) {
vm.prototype.$listMove = listMove
}
}
8.数组扁平化加去重
let arr=[1,2,[3,4,[3,5],[55,5]],[3,5],9]
console.log([...new Set(arr.flat(Infinity))])
9.new关键字做了那些事情?自己实现一个_new方法
1.像普通函数执行一样形成一个私有作用域 ..形参赋值 ..变量提升 2.默认创建一个对象,让函数中的this指向这个对象,这个对象事当前类的实例 3.代码执行 4.把当前对象返回
function Dog(name){
this.name=name
}
functon _new(CLA,...arg){
//let obj={}
//obj.__proto__=CLA.prototype
let obj=Object.create(CLA.prototype)
CLA.call(obj,...arg)
return obj
}
let d1=_new(Dog,'aaa')
let d2=new Dog('bbb')
10.闭包,我理解的闭包概念
函数执行后形成了不被销毁的栈内存,保存了私有变量,就是闭包
var i=5
function fn(i){
return function (n){
console.log(n+(++i))
}
}
var f=fn(1)
f(2) //4
fn(3)(4) //8
fn(5)(6) //12
f(7) //10
console.log(i)//5
var i=20
function fn(){
i-=2;
return function (n){
console.log((++i)-n)
}
}
var f=fn()
f(1) //18
f(2)//18
fn()(3)//16
fn()(4)//14
f(5)//14
console.log(i)//19
这两个很变态的闭包练习题,我终于搞通了
11,常用es6特性
1,let const 块级作用域
2,解构赋值 let [a,b]=[2,3]
3,对象合并 object.assigin(obj1,obj2)
3,promise 对象
4,对象的导入导出 import export
12,call bind apply 区别
call把函数当作普通函数执行,函数中的this指向call执行时的第一个参数,后面的参数当作普通参数传递给函数,如果一个参数都没有,在非严格模式下 this指向window 严格模式下指向undefind,如果传参null或者undefind,非严格模式下指向window,严格模式下写谁就指向谁,自己实现call方法
Function.prototype.call=function (context){
let args=[...arguments]
context=context||window
context.$fn=this
args=args.slice(1)
let n=context.$fn(...args)
delete context.$fn
return n
}
let obj={a:111}
function fn(m,n){
console.log(this) //{a: 111, $fn: ƒ}
return m+n
}
let a=fn.call(obj,10,20)
console.log(a) //30
apply和call用法和效果一样,只是又一点不同,apply的第二个及其以后的参数要是个数组
Function.prototype.apply=function (context){
context=arguments[0]
context=context||window
context.$fn=this
args=arguments[1]
let n=context.$fn(...args)
delete context.$fn
return n
}
let obj={a:111}
function fn(m,n){
console.log(this) //{a: 111, $fn: ƒ}
return m+n
}
let a=fn.apply(obj,[10,20])
console.log(a) //30
bind 返回一个函数,不会立即执行
Function.prototype.bin=function (context){
context=context||window
let args=[...arguments][1]
context.$fn=this
return function (){
context.$fn(...args)
delete context.$fn
}
}
let obj={a:11}
function fn(a,b){
console.log(this,a+b)
}
let f=fn.bin(obj,[2,9])
f() //11
13.重写一下数组的方法
Array.prototype._each=function (callback){
for(let i=0;i<this.length;i++){
callback(this[i],i)
}
}
Array.prototype._map=function (callback){
let newarr=[]
for(let i=0;i<this.length;i++){
newarr.push(callback(this[i],i))
}
return newarr
}
Array.prototype._fillter=function (callback){
let newarr=[]
for(let i=0;i<this.length;i++){
let bl=callback(this[i],i)
if(bl){
newarr.push(this[i])
}
}
return newarr
}
14,函数重载和重写
函数名相同,函数的参数个数和类型不同,叫函数重载,前端没有函数重载概念,可以在函数内判断实现,重载是后端语言为了减轻并发压力实现的方法,typescript也实现了函数的重载
function fn(a){}
function fn(a,b){}
function fn(a,b,c){}
重写是类的继承中 子类可以重写父类中的方法
15,javascript 中的设计模式
1,单例模式
2,工厂模式
3,组合模式,原型模式
4,订阅发布模式
5,观察者模式
16,js判断对象为空的常用方法
1,JSON.stringfy(obj)=="{}"
2,object.keys(obj).length
17, Object.create 的作用,手写一个create函数
1.他会生成一个新的空对象
2.这个空对象可以继承目标对象的属性和方法
let obj={a:1}
function create(O){
let f={}
f.prototype=O
return f
}
let b=create(obj)
console.log(b,b.a)//{},1
18,js实现冒泡排序
function sort(arr){
let newArr=[...arr]
let len=newArr.length
for(let i=0;i<len-1;i++){
for(let j=0;j<len-1-i;j++){
if(newArr[j]>newArr[j+1]){
[newArr[j],newArr[j+1]]=[newArr[j+1],newArr[j]]
}
}
}
return newArr //返回一个排序后的新数组
}
myArr = [20,18,27,19,35];
let arr2=sort(myArr)
console.log(myArr,arr2)
19.js数据类型转换的方法
再js中数据类型转换有三种情况,
转换未布尔Boolean()
转为数字Number(),ParseInt(),ParseFloat()
转为字符串toString(),String()
null和undefined不可调用toString()方法。
20.js中判断数据类型的方法
typeof instandof Object.prototype.toString.call()
21,js有哪些内置对象
1),值属性,这些全局属性返回一个简单值这些值没有自己的属性和方法例如:Infinity,NaN,undefined,null
2).函数属性:parseInt(),parseFloat(),eval()
3).基本对象,Object Function Boolean Symbol Error
4).数字和日期对象,Number Math Date
5),字符串对象 String RegExp
6),可索引对象Array
7),结构化数据 JSON
8),控制抽象对象,Promise , Generator
9)反射,Reflect , Proxy
10),...
22,递归实现1到100求和
function sum(){
let result=0
let i=1
return function calc(){
result+=i++
return i>100?result:calc()
}()
}
23.防抖和节流
防抖是一个频繁执行的事件我只需要最后一次的结果
let debounce = (fn, delay) => {
let timer = null;
return (...args) => {
clearTimeout(timer);
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
}
}
节流是降低频繁事件的执行频率
let throttle = (fn, delay) => {
let flag = true;
return (...args) => {
if (!flag) return;
flag = false;
setTimeout(() => {
flag = true;
fn.apply(this, args);
}, delay);
}
}
24,数据类型检测
typeof
constructor
instandof
Object.prototype.toString.call()
25,this 的三种使用场景
1.全局下的this 非严格模式下指向window 严格模式指向 undefind
2.构造函数中的this 指向实例
3.方法中的this指向带哦用此方法的对象
26 正则去空格的常用方法
//去除空格
String.prototype.Trim = function() {
return this.replace(/\s+/g, "");
}
//去除换行
function ClearBr(key) {
key = key.replace(/<\/?.+?>/g,"");
key = key.replace(/[\r\n]/g, "");
return key;
}
//去除左侧空格
function LTrim(str) {
return str.replace(/^\s*/g,"");
}
//去右空格
function RTrim(str) {
return str.replace(/\s*$/g,"");
}
//去掉字符串两端的空格
function trim(str) {
return str.replace(/(^\s*)|(\s*$)/g, "");
}
//去除字符串中间空格
function CTim(str) {
return str.replace(/\s/g,'');
}
//是否为由数字组成的字符串
function is_digitals(str) {
var reg=/^[0-9]*$/; //匹配整数
return reg.test(str);
}
27 js检测一个变量是string
1 typeof x === "string"
2 typeof(x) === "string" // 小写
3 x.constructor === String // 大写类型
28 异步函数
async function async1 () {
console.log('async1 start')
await async2(); console.log('async1 end')
}
async function async2 () {
console.log('async2')
}
console.log('script start')
setTimeout(function () {
console.log('setTimeout')
}, 0)
async1()
new Promise(function (resolve) {
console.log('promise1')
resolve()
}).then(function () {
console.log('promise2')
})
console.log('script end')
29 js 宏任务,微任务,执行顺序
宏任务: js宿主 全局任务 setTimeOut,setInterval,setImmediate, I/O render
微任务: js自己的任务,process.nextTick (node.js中进程相关的对象), Promise, Object.observer, MutationObserver
宏任务队列可以有多个,微任务队列只有一个,微任务优先于宏任务执行
30,得到两个数组的交集,两个数组的元素为数字或者字符串
function getIntersection(arr1,arr2)=>{
let len = arr1.length < arr2.length ? arr1.length : arr2.length;
let i = -1;
let res = [];
if (arr1.length < arr2.length) {
while( ++1 < len ) {
const item = arr1[i];
if (arr2.indexOf(item) > -1) res.push(item)
}
} else {
while( ++1 < len ) {
const item = arr2[i];
if (arr1.indexOf(item) > -1) res.push(item)
}
}
}