「2022」JS

目录

【常问】

❗7)深拷贝和浅拷贝

考点:(1)能答上基本数据类型和引用数据类型的关系(2)能答上堆栈关系

js的数据类型有基本数据类型和引用数据类型,基本数据类型是存储在栈中,引用数据类型的地址是存储在栈中,值是存储在堆中的。

深拷贝复制的是对象的值和对象的引用,新对象和原对象不会共享内存,修改复制后的对象不会影响原对象。
浅拷贝复制的是对象的引用,新对象和原对象还是共享同一块内存,如果修改复制后的对象,原对象也会跟着改变。

深拷贝实现
1.1 JSON对象

JSON.parse(JSON.stringify(value))
JSON.stringify把对象转成字符串,再用JSON.parse把字符串转成新的对象
缺点:不能复制undefined、function、symbol的类型

const info = { name: 'why', age: 18, friend: { name: 'lili' } }
const obj = JSON.parse(JSON.stringify(info))
info.friend.name = 'cici'
console.log(obj.friend.name) //lili
1.2 递归
function deepClone(obj) {
	//判断储存的类型
  let objClone = Array.isArray(obj) ? [] : {};
  if (obj && typeof obj === 'object') {
    //循环遍历obj的key
    for (let key in obj) {
      if (obj[key] && typeof obj[key] === 'object') {
        //循环递归直到属性不为一个object为止
        objClone[key] = deepClone(obj[key]);
      } else {
        objClone[key] = obj[key];
      }
    }
  }
  return objClone;
}
let person1 = {
  name: '园丁',
  job: {
    age: 18,
    address: '高新',
    id: {
      idCard: 5003888
    }
  }
};
let person2 = deepClone(person1);
person2.job.age = 19
person2.job.id.idCard = 155
console.log(person1, 'person1');
console.log(person2, 'person2');
1.3 jQuery的$.extend()

语法

<script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js">
</script>
<script>
  let person1 = {
    name: '园丁',
    job: {
      age: 18,
      address: '高新',
      id: {
        idCard: 5003888
      }
    }
  };
  let person2 = $.extend(true, {}, person1);
  person2.job.age = 19
  person2.job.id.idCard = 155
  console.log(person1, 'person1');
  console.log(person2, 'person2');
</script>
1.4 通过第三方库loadsh,深拷贝_.cloneDeep(value)
浅拷贝实现
1.1 Object.assign({}, info)

ES6对象的合并,第一个参数必须是个空对象。会把info对象所有的属性拷贝到{}中,会将拷贝的对象作为返回值返回出去用obj接收,会创建一个新的对象,拷贝所有的属性,保存对象的引用

const info = { name: 'why', age: 18, friend: { name: 'lili' } }
const obj = Object.assign({}, info)

info.name = 'kobe'
console.log(obj.name) //kobe

info.friend.name = 'cici' //把info里面对象的属性值改了,就等于把拷贝的obj的值也改了
console.log(obj.friend.name) //cici
1.2 展开运算符…
const fxArr = ["One", "Two", "Three"]
const fxArrs = [...fxArr]
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
1.3 Array.prototype.concat(),Array.prototype.slice()

都不会改变原数组

const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.concat()
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
const fxArr = ["One", "Two", "Three"]
const fxArrs = fxArr.slice(0)
fxArrs[1] = "love";
console.log(fxArr) // ["One", "Two", "Three"]
console.log(fxArrs) // ["One", "love", "Three"]
1.4 通过第三方库loadsh,浅拷贝_.clone(value)

❗6)事件循环(event loop)?宏任务微任务有了解吗?

因为js是单线程的,同一时间只能做一件事情,所以所有的任务都需要排队。js执行的线程就称为主线程,当主线程执行的时候,遇到同步任务就直接运行,遇到异步任务会创建任务队列把异步任务放到队列里面。当同步任务执行完成以后,再去执行任务队列中的异步任务。异步任务又分为宏任务和微任务,微任务会创建一个微任务队列,宏任务会创建宏任务一个队列,会先把微任务全部放到执行栈中执行,最后再从宏任务队列中取出一个放入执行栈中执行,执行完后,再取一个,直到执行完所有的宏任务。当任务执行完以后,重复这样的查找执行,整个这个过程和机制,称为js的事件循环。

宏任务:setTimeout,setInterval,ajax,Dom事件回调
微任务:process.nextTick(Node独有),Promise.[then/catch/finally],async/await

❗2)事件委托(事件代理)

比如说我时候想做一个事件委托,就是有一个ul,还有li,我点击这个li,我不可能对每个li都绑定点击事件,我需要做一个事件委托,这时候可以怎么做啊,我要绑定这个事件

事件委托:将元素的事件委托给它的父级或者更外级的元素处理,它的实现机制就是事件冒泡。

❗阻止事件冒泡和默认行为

阻止事件冒泡
W3C:event.stopPropagation()
IE:event.cancelBubble = true

阻止事件默认行为
W3C:event.preventDefault
IE:event.returnValue = false
场景:a标签href属性上的跳转;鼠标右键呼出菜单

return false方法阻止事件冒泡和默认行为
JS的return false只会阻止默认行为
jQuery的return false既阻止默认行为又阻止对象冒泡

<div id="father" onclick="alert('father')">
  <h3>father</h3>
  <div id="son" onclick="alert('son')">
    <h3>son</h3>
    <a href="https://www.baidu.com" id="btn">son</a>
  </div>
</div>
<script>
  /*阻止冒泡*/
  $('#son').click(function (e) {
    e.stopPropagation();
  })
  /*阻止默认事件*/
  $('#btn').click(function (e) {
    e.preventDefault();
  })
  /*return false既会阻止默认行为也会停止冒泡*/
  $("#son").on('click', function () {
    return false
  })
</script>

❗4)原型和原型链

原型:每个函数都有一个prototype属性,它指向的是原型对象(Person.prototype),这个原型对象的作用是共享对象的所有属性和方法。所有的原型对象里都有一个constructor属性,它指向的是创建它的构造函数。

原型链:每个对象都有个__proto__属性,通过这个属性可以访问到原型对象。当访问一个实例的属性时,会先在当前实例上找,如果没找到就会通过__proto__到原型对象上一级一级的去查找,最终会找到顶级对象Object.prototype,它指向的是null。构造函数、原型对象、实例之间的联系就构成了原型链。

hasOwnProperty是判断一个对象是否有某个属性或对象。var obj={}; obj.hasOwnProperty("val") //判断obj对象是否具有val属性

注释:

  1. prototype属性(显式原型)、constructor(构造器)、__proto__属性(隐式原型)
  2. constructor它为了让构造函数构造出来的所有的对象都能找到自己的构造器
  3. 通过构造函数new创建出来的对象是"实例对象"
    在这里插入图片描述
//这个是函数
function fn(){
	//to do something
}

//这个是方法 通过对象调用的javascript函数
var obj = {
	//两种写法都可以,用逗号分隔
  fn: function () {
    console.log("xixi")
  },
  fn1() {
    console.log("hahha")
  }
}
obj.fn()//方法调用
obj.fn1()//方法调用

//这个是构造函数
function Fn(){}

//这个obj就是实例对象
var obj = new Fn()

❗2)构造函数,new的过程

创建对象三种方式:
①对象字面量var obj = {}
②系统自带的构造函数var obj = new Object()
③自定义构造函数

构造函数是一种特殊的函数,主要用来初始化对象,为对象成员变量赋初始值,它需要跟new一起使用,然后它的首字母要大写。(有浪费内存问题)

new的过程:

  1. 创建一个空的对象
  2. 将新创建的空对象的隐式原型proto指向构造函数的原型对象prototype
  3. 将构造函数中的this指向这个空对象
  4. 判断构造函数返回值的类型。如果没有返回值或返回值是基本数据类型,就把这个新创建的对象返回;如果返回值是引用数据类型,就返回这个引用类型的对象(所以构造函数里面不需要return)
// 定义一个Person构造函数
function Person(name, age){
  this.name = name;
  this.age = age;
}
//另外定义一个createNew()用来模拟new关键字的执行过程
function createNew(fn, ...args) {
	 // 1. 创建一个空对象
  let obj = {}; 
  // 2. 将新对象的__proto__属性指向构造函数的原型对象prototype
  obj.__proto__ = fn.prototype; 
  // 3.将构建函数的this指向新对象
  let result = fn.apply(obj, args);
   //console.log(result) //fn.apply()的返回值就是fn的返回值,由于例子中Person()没有返回值,所以此处返回值是undefined
  //4. 根据返回值判断。如果构造函数返回的是引用数据类型,则直接返回这个结果。否则,返回新创建的对象
  return result instanceof Object ? result : obj; 
}

//执行createNew()看一下它的返回结果
let createNew1 = createNew(Person, 'yy', 18)
console.log(createNew1)//Person {name: "yy", age: 18}

//使用new直接操作Person()看一下它的结果
let person = new Person('yy',18)
console.log(person )//Person {name: "yy", age: 18}

//可以看到createNew()的结果与使用new得到的结果一致,说明createNew()代表的就是new内部的原理。

❗3)js数据类型有哪些?区别?

基本数据类型:String、Number、Boolean、Null、Undefined、Symbol、Bigint
引用数据类型:Object、Array、Function

区别在于存储数据的地方是不同的。
基本数据类型存放在栈中,引用数据类型在栈中保存指针,在堆中保存对象值;

❗4)闭包?特性?实际项目中有哪些应用场景

什么情况会触发闭包:多个函数互相嵌套,内部的函数返回到了外部。

定义:
红宝书:闭包是指有权访问另外一个函数作用域中的变量的函数。
阮一峰:闭包就是能够读取其他函数内部变量的函数(可以把闭包简单理解成"定义在一个函数内部的函数"。)

闭包有3个特性:
①函数嵌套函数;②外部函数可以访问内部函数的变量;③参数和变量不会被垃圾回收机制回收;

优点:可以将一个变量长期存储在内存中,用于缓存;可以避免全局变量的污染。

缺点:
闭包会导致原有作用域链不释放,造成内存泄漏;
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,会造成网页的性能问题。解决方法是,在退出函数之前,将不使用的局部变量全部删除。

应用场景:
①防抖节流函数

//闭包:既然f2可以读取f1中的局部变量,那么只要把f2作为返回值,就可以在f1外部读取它的内部变量了
function f1(){
	var n = 999;
	function f2(){
		alert(n);
	}
	return f2;
}
var result = f1();
result(); // 999

②事件绑定的回调方法
③setTimeout的延时回调

❗3)防抖和节流是什么?应用场景?

防抖和节流都是为了限制函数的执行次数,防止高频调用函数带来的性能损耗和卡顿,节省计算资源。

  • 防抖:多次触发事件后,在n秒内只执行最后一次;如果在n秒内又触发了事件,就会重新计时。
  • 节流:多次触发事件后,在n秒内只执行一次。
  • 防抖应用场景:搜索框搜索输入/输入手机号邮箱验证时的检测(停止输入时才发送请求),窗口调整resize。
  • 节流应用场景:滚动加载更多/滚到底部监听,按钮重复点击(刷新按钮、表单重复提交)。

实现方式一:通过第三方库lodash/underscoreinputEl.oninput = _.debounce(inputChange, 2000),_.throttle
实现方式二:

/*防抖*/
function debounce(fn, delay) {
    let timer = null;
    return function(...args){
      clearTimeout(timer);
      timer = setTimeout(() => {
        fn.apply(this, args);
      }, delay)
    }
}

/*节流*/
function throttle(fn, delay) {
    let flag = true;
    return function (...args) {
      if (!flag) return;
      flag = false;
      setTimeout(() => {
        fn.apply(this, args);
        flag = true;
      }, delay)
    }
}

❗对象继承的实现方法

  1. ES6的class继承。
//使用class构造一个父类;再使用class构造一个子类,并使用extends实现继承,super指向父类的原型对象
class Parent{
	constructor(){
		this.age = 18;
	}
}
class Child extends Parent{
	constructor(){
		super();
		this.name = 'haha'
	}
}
let ChildList = new Child()
console.log(ChildList)
  1. 原型链继承。缺点:过多的继承了没用的属性。
function Parent() {
  this.age = 18
}
function Child() {
  this.name = 'xixi'
}
Child.prototype = new Parent()
let ChildList = new Child()
console.log(ChildList, ChildList.age)
  1. 借用构造函数。缺点:不能继承借用构造函数的原型;每次构造函数都要多走一个函数。
function Parent() {
  this.age = 18
}
function Child() {
  this.name = 'xixi'
  Parent.call(this)
}
let ChildList = new Child()
console.log(ChildList, ChildList.age)
  1. 组合继承。
function Parent() {
  this.age = 18
}
function Child() {
  Parent.call(this)
  this.name = 'xixi'
}
Child.prototype = new Parent()
let ChildList = new Child()
console.log(ChildList, ChildList.age)

❗递归

递归就是函数在运行的过程中调用自己。
必须具备两个条件:一个是调用自己,另一个是有终止条件。
运用场景:阶乘、深拷贝

【ES6】

❗5)ES6有哪些新特性

只用说前7个

  1. 变量声明let和const
  2. 解构赋值(先提取,再赋值)
var names = ["abc", "bbc", "cbc"];
//对数组的解构:[]
var [item1, item2, item3] = names
console.log(item1, item2, item3)//abc bbc cbc
//解构后两个元素
var [, itema, itemb] = names
console.log(itema, itemb)//bbc cbc
  1. 箭头函数
  2. Promise(异步函数)
  3. class类
  4. 模块化(import / export / export default)
import { sum } from 'js/index.js'; //只导入一个
import { sum, sub, add } from 'js/index.js'; //导入多个
export default sum//导出
  1. 扩展运算符…
  • 数组的扩展(用于取出参数对象所有可遍历属性然后拷贝到当前对象)
/*基本用法*/
let person = {name: "Amy", age: 15};
let someone = { ...person };
someone;  //{name: "Amy", age: 15}

/*可用于合并两个对象*/
let age = {age: 15};
let name = {name: "Amy"};
let person = {...age, ...name};
person;  //{age: 15, name: "Amy"}
//扩展运算符在等号右边, 将数组中的数据解构开
let arr1 = [1, 3, 5];
let arr2 = [2, 4, 6];
let arr = [...arr1, ...arr2];
// let arr = [1, 3, 5, 2, 4, 6];
  • 函数参数的扩展:不定参数(不定参数用来表示不确定参数个数,形如,…变量名)
function f(...values){
    console.log(values.length);
}
f(1,2);      //2
f(1,2,3,4);  //4
  1. 模板字符串反引号``(可以换行可以嵌套变量,字符串插值${})
  2. 对象字面量的增强写法
/*属性的增强写法*/
const obj = { name: name, age: age } //ES5写法
const obj = { name, age } //ES6增强写法
/*函数的增强写法*/
bbb:function(){} //ES5写法
bbb(){} //ES6增强写法
  1. 基本数据类型(Symbol),表示独一无二的值,最大的用法是用来定义对象的唯一属性名

❗4)let、const、var的区别

ES5中的作用域有:全局作用域、局部(函数、块级)作用域。
ES6中新增了块级作用域。块作用域由{}包括,if语句和for语句里面的{}也属于块级作用域。

  • 块级作用域:var没有块级作用域,let和const有块级作用域
  • 变量提升(变量在声明之前就能使用):var有变量提升,let和const没有
  • 重复声明:var可以重复声明变量,let和const不可以
  • 设置初始值:声明变量的时候,var和let可以不设初始值,const必须设置初始值
  • 指针指向(重新赋值):var和let可以修改指针指向的,const不能修改
  • 全局变量:使用var声明的全局作用域变量属于window对象(会被添加到全局对象的属性中),let和const不属于。(var在函数内部是局部变量,在函数外部是全局变量)

let const区别:
let可以不设初始值,const必须设置初始值;
let可以重新赋值,const不可以;let a = 10; a = 20;

总结:
let和const有块级作用域,var没有
var有变量提升,let和const没有
var可以重复声明,let和const不可以
var和let可以不设初始值,const必须设置初始值
var和let可以重新赋值,const不可以
var声明的全局变量会挂载到window上,let和const不会

❗2)箭头函数与普通函数的区别

  • 声明方式。普通函数是用关键字function;箭头函数就是=>比普通函数的声明更简洁
  • this指向。普通函数有this;箭头函数没有自己的this(会捕获其所在的上下文的this作为自己的this,如果没有上下文环境对象,那么就指向最外层的window)
  • arguments。普通函数可以使用arguments来访问传递给函数的参数;箭头函数没有自己的arguments,可以用扩展运算符…代替arguments对象
  • new调用。普通函数可以作为构造函数使用new调用;箭头函数没有prototype(原型),不能作为构造函数使用new调用
  • 作用域提升。普通函数有作用域提升,可以在定义前调用;箭头函数不可以
  • 箭头函数没有new.target。new.target是用来检测函数是否被当做构造函数使用的,会返回一个指向构造函数的引用。

❗3)Promise,业务场景?

Promise是异步编程的一种解决方案,它是一个对象,可以获取异步操作的消息。

优点:
支持链式调用,避免了层层嵌套的回调函数,解决了回调地狱的问题。
缺点:
首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
第三,当处于Pending状态时,无法得知目前进展到哪一个阶段。
三个状态:
pending:进行中/等待中;resolved:成功会回调then;rejected:失败会回调catch
两个过程:
pending→resolved,pending→rejected

❗2)promise的API方法有哪些?

Promise.all
可以将多个Promise实例包装成(放在一个数组中)一个新的Promise实例。当全部成功时才会返回成功,有一个失败就返回失败的

Promise.all([
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('result1')
      },2000)
    }),
    new Promise((resolve, reject) => {
      setTimeout(() => {
        resolve('result2')
      },1000)
    })
]).then(results => {
  console.log(results)
})

Promise.race()

Promise.race([p1, p2, p3])

最先得到哪个结果,就返回哪个结果,不管结果本身是成功状态还是失败状态

Promise.any()

Promise.any([p1, p2, p3])

只要有一个成功,就返回成功的promise,如果没有一个成功,就返回一个失败的promise

Promise的基本用法及参数?

①使用new实例化一个Promise对象,Promise的构造函数中传递一个参数。这个参数是一个函数,该函数用于处理异步任务;
②并且传入两个参数:resolve和reject,分别表示异步执行成功后的回调函数和异步执行失败后的回调函数;
③通过promise.then() 处理返回结果。
④Promise自身有all、any、race、reject、resolve方法,原型上有then、catch、finally方法。

const p = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve("hello")
  }, 1000)
}).then((res) => {
  console.log(res)
}).catch((err) => {
  console.log(err)
})

❗Promise为什么可以一直.then

因为返回了一个新的promise,新的promise能继续调用.then

Promise中的reject和catch处理上有什么区别?

reject是用来抛出异常,catch是用来处理异常
reject是Promise的方法,而catch是Promise实例的方法

const定义的对象属性能否改变

可以改变对象内部的属性,但是对象的指针不能改变

const p = {
  name: 'cc',
  age: 18
}
p.name = 'aa' //p对象的name属性是可以改变的
p = {
  name: 'bb',
  age: 18
}// 如果让p指向一个新对象就会报错

const定义的基本数据类型的变量确实不能修改,因为对象是引用类型的,p中保存的仅是对象的指针,const仅保证指针不发生改变,所以是被允许的。也就是说const定义的引用类型只要指针不发生改变,其他的不论如何改变都是允许的。

箭头函数和箭头函数的this指向

箭头函数只有一个参数时,可以省略小括号;箭头函数的函数代码块只有一行代码可以省略{}和return

//普通写法
setTimeout(function(){
},1000//箭头函数写法
setTimeout(()=> {
},1000)

箭头函数没有自己的this,会向外层作用域中一层一层的查找直到有this的定义。

JS基础

❗栈stack和堆heap

栈存储的是基本数据类型和引用数据类型的地址,会指向堆内存中的值;
堆存储的是引用数据类型的值;

栈的特点:先进后出,后进先出;
栈内存可以称为一级缓存,由垃圾回收器自动回收;
堆的特点:先进先出,后进后出;
堆内存可以称为二级缓存,堆中的对象不会随时释放,一般需要开发人员自己回收它;

基本数据类型赋值相互不影响,引用数据类型赋值会影响原对象;

var num = 1;   // 栈 
var name = '前端'; // 栈

// 变量user存在栈中,{name:'河畔'}存在堆内存中
var user = { name: '河畔' }; 
// 变量arr存在栈中,[1, 2, 3] 作为对象存在堆内存中
var arr = [1, 3, 5]; 

因此当我们要访问堆内存中的引用数据类型时,实际上我们首先是从栈中获取了该对象的指针,然后再从堆内存中取得我们需要的数据。

❗js中的内存泄露

❗null和undefined的区别

  1. undefined 和 null 都是基本数据类型;
  2. undefined 表示的是未定义,null 表示的是空对象;使用 typeof 对null进行判断会返回 “object”;
  3. 当使用双等号对两种类型的值进行比较时会返回 true,使用三个等号时会返回 false。

❗0.1+0.2=0.3返回true还是false?怎样可以返回true?

返回false

❗2)typeof返回的数据类型有哪些?

typeof返回的数据类型有:string、number、boolean、undefined、object、function
typeof两种写法:typeof(num)typeof num
typeof输出结果:

  • typeof null结果:object
  • typeof []结果:object
  • typeof {}结果:object
  • typeof NaN结果:number
  • typeof undefined结果:undefined

❗如何判断一个数据是NaN

①isNaN(value)是NaN时会返回true不是NaN会返回false,每次判断会先将值转成数值然后进行判断

console.log(isNaN(NaN))   //true
console.log(isNaN(123))   //false
console.log(isNaN('1531sad'))   //true

②Object.is(value1, value2)判断两个值是否为同一个值

console.log(Object.is("a", NaN))   //false
console.log(Object.is(1, NaN))   //false
console.log(Object.is(NaN, NaN))   //true

❗判断数据类型的方法

typeof可以判断基本数据类型,不能判断引用数据类型;
instanceof返回的是布尔值,适合判断引用数据类型。

  • typeof
    typeof("aaa") --> string无法判断引用类型(数组函数对象)和null,返回的都是object;
  • instanceof
    [1,2,3] instanceof Array --> true判断A是否为B的实例,instanceof后面一定要是对象类型,并且大小写不能错;
  • constructor
    let num = 1; console.log(num.constructor); --> number(){}返回创建实例对象的 Object 构造函数的引用,所有对象都会从它的原型上继承一个 constructor属性。无法判断null和undefined因为它们没有构造函数;
  • Object.prototype.toString.call(需要判断的值):
    Object.prototype.toString.call(1)基本上所有对象的类型都可以通过这个方法获取到(Boolean、Number、String、Function、Array、Date、RegExp、Object、Error等类型)。

判断数组的方法

let arr = [1, 2, 3];以下6种方法都返回true
arr instanceof Array:判断arr是否是由构造函数Array实例化得到的
arr.constructor === Array:判断数组arr的构造函数属性是否等于构造函数本身
Array.prototype.isPrototypeOf(arr):判断构造函数Array的原型是否是arr的原型对象
Object.getPrototypeOf(arr) === Array.prototype:获取arr的对象原型属性和构造函数Array的对象原型属性相比较
Object.prototype.toString.call(arr) --> [Object Array]:最准确。会返回[Object type],其中 type为对象的类型。判断获取的arr的对象原型经过字符串化后的类型是否等于’[Object Array]’
Array.isArray(arr):最准确。ES6新增的方法。

❗2)数组常用操作方法

文章

操作方法:

  1. 增:push()unshift()
  2. 删:pop()shift()
  3. 增删:splice()
  4. 改:截取slice()、拼接concat()、转换toString()join()
  5. 查:indexOf()find()includes()

排序方法:sort()reverse()
迭代方法:for offor in(适合遍历对象)、forEach()map()reduce()filter()every()some()
去重方法:new Set()

❗2)map和forEach有什么区别

共同点:
都是遍历数组的方法

不同点:
map() 不会改变原始数组,会返回一个新的数组
forEach() 会改变原始数组,返回值为undefined

❗splice和slice和split区别

区别:splice会改变原数组,slice,split不会改变原数组。

splice截取(数组) 。功能一是删除数组元素;功能二是删除并插入元素:

let arr = [1,2,3,4,5,6,7,8,9]
// 从下标为3的项开始,依次向后删除2个元素,返回被删除的元素数组:[4, 5],原数组改变为:[1, 2, 3, 6, 7, 8, 9]
arr.splice(3,2)

slice切割(字符串/数组)。

let str = 'hello world'
// 截取下标 [2,5) 区间的字符串,左闭右开,结果为:llo
let str2 = str.slice(2,5)  

split分割(字符串)。

var date1 = "2017-08-12";
var date1Str = date1.split("-");//['2017','08','12']

❗for in和for of区别

for in(遍历对象)遍历的是对象的属性名,数组的键名(key)
for of(ES6 遍历数组)遍历的是数组的值(value)

❗怎么遍历多层嵌套的数组?

❗2)this指向

详解 this是函数的内置对象,所以this只能出现在函数里。

  • 【默认绑定】在普通function函数调用时,this指向全局对象window(严格模式下指向undefined);
  • 【隐式绑定】在对象中的方法调用时,this指向该方法所属的对象;
  • 【显示绑定】
    • call,apply,bind显示绑定后,this指向绑定的对象;
    • 内置函数
      • 在事件绑定的方法时,this指向绑定事件的DOM对象;
      • setTimeout,this指向的是window
  • 【new绑定】在new构造函数调用时,this指向实例对象;
  • 箭头函数中的this会向外层作用域中一层一层的查找直到有this的定义;

优先级:new绑定 > 显示绑定> 隐式绑定 > 默认绑定

❗call、apply、bind有什么区别?

Fn.call(obj, 'arg1', 'arg2', 'arg3', '...')
Fn.apply(obj, ['arg1', 'arg2', 'arg3', '...'])
Fn.bind(obj, ['arg1', 'arg2', 'arg3', '...'])

相同:

  • 都是用来改变函数的this指向;
  • 第一个参数都是this要指向的对象;

不同点:

  • 传参不同。apply和call传入的参数列表形式不同。apply接收arguments,call接收参数列表
  • 执行机制不同。call和apply会立即执行函数,bind执行后不会立即调用原函数,而是返回一个新函数,bind需要调用它才会被执行 。

❗js中有哪些事件

1)点击事件:
onclick:单击事件
ondblclick:双击事件

2)焦点事件
onblur:失去焦点
onfocus:元素获得焦点。

3)加载事件:
onload:一张页面或一幅图像完成加载。

4)鼠标事件:
onmousedown 鼠标按钮被按下。
onmouseup 鼠标按键被松开。
onmousemove 鼠标被移动。
onmouseover 鼠标移到某元素之上。
onmouseout 鼠标从某元素移开。

5)键盘事件:
onkeydown 某个键盘按键被按下。
onkeyup 某个键盘按键被松开。
onkeypress 某个键盘按键被按下并松开。

6)选择和改变事件:
onchange 域的内容被改变。
onselect 文本被选中。

7)表单事件:
onsubmit 确认按钮被点击。
onreset 重置按钮被点击。

❗js里有变量提升的问题?怎么解决这个问题?

变量提升的问题可以使用let或者const定义变量

js获取一个对象上所有的key有哪些方式

Object.keys( )不会走原型链,而for in会走原型链

  1. for in
let obj = {
 name: '王大锤',
 age: '18',
 weight: '70kg'
}
for(let key in obj) {
 console.log(key); // name age weight
 console.log(obj[key]); // 王大锤 18 40kg
}
  1. Object.keys
let colors = {
  color1: 'pink',
  color2: 'red'
};
let myColors = Object.keys(colors);
console.log(myColors); // ["color1", "color2"]

js怎样添加、移除、移动、复制、创建和查找节点?

js操作DOM的常用API:

创建:
document.createElement(“p”); 创建新的<p> 元素
document.createTextNode() 创建文本节点

添加、移除、替换、之前插入、之后插入:
appendChild() 添加/追加
removeChild() 移除
replaceChild() 替换
insertBefore() 之前插入
insertAfter() 之后插入
cloneNode() 复制

查找:
document.getElementById:根据ID查找元素
document.getElementsByClassName:根据类名查找元素
document.getElementsByTagName:根据标签查找元素
document.querySelector
document.querySelectorAll

其他:
setAttribute 添加一些属性
innerHTML 获得html内容

js中的=====有什么区别?

= = 只要等号两边的值相等,就会返回true,在判断的时候会自动进行类型转换。
= = = 表示全等,需要值和类型完全相等。

js中哪些数据在if判断时是false

0、false、null、undefined、“”、NaN 判断为false

❗什么是回调函数

当一个函数做另一个函数的参数时,这个函数就叫回调函数。

作用域和作用域链

作用域[[scope]]:
在一定的空间内可以对数据进行操作,这个空间就是作用域,有全局作用域和局部作用域(函数作用域和块级作用域)
全局作用域:任何地方都能访问到这个变量;
局部作用域:
①函数作用域是只有在函数内部可以访问到这个变量,只有在函数执行的时候存在,执行完就销毁;
②es6新增的let const用来创建块级作用域,块级作用域由{}包括,if语句和for语句里面的{}也属于块级作用域.

作用域链:
查找变量的时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查找,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

比如函数A内部定义了一个函数B,然后这个函数B就可以访问函数A里面的变量和方法,函数B会先在自己的作用域中查找变量,如果找不到就向外层作用域去查找,这种一层一层向上依赖的关系就构成了作用域链。
(从作用域链的顶端依次向下查找)

阮一峰:子对象会一级一级地向上寻找所有父对象的变量

//如何从外部读取局部变量?在函数的内部,再定义一个函数。
function f1(){
  var n = 999;
  function f2(){
	  alert(n); //999
  }
}
//函数f2就被包括在函数f1内部,这时f1内部的所有局部变量,对f2都是可见的

JS对象/类

创建对象有几种方法

  1. 通过对象字面量var obj = {}
  2. 通过构造函数function Person(){}; var obj = new Person()
  3. Object.create()var person = {}; var obj = Object.create(person)

JS库

同步与异步的区别

同步:同步是指一个进程在执行某个请求的时候,如果该请求需要一段时间才能返回信息,那么这个进程会一直等待下去,直到收到返回信息才继续执行下去。

异步:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态,当有信息返回的时候会通知进程进行处理,这样就可以提高执行的效率了。

❗ajax同步和异步的区别

ajax中根据async的值不同分为同步(async = false)和异步(async = true)两种执行方式。
async默认值为false是同步。同步请求即是当前发出请求后,浏览器什么都不能做,必须得等到请求完成返回数据之后,才会执行后续的代码。
async默认值为true是异步。异步请求就当发出请求的同时,浏览器可以继续做任何事,Ajax发送请求并不会影响页面的加载与用户的操作。

❗ajax的实现?

$.ajax({
    url: "test.json", //json文件位置
    type: "GET", //请求方式为get
    dataType: "json", //返回数据格式为json
    success: function(data) { //请求成功完成后要执行的方法 
        //each循环 使用$.each方法遍历返回的数据date
        $.each(data.first, function(i, item) {
            var str = '<div>姓名:' + item.name + '昵称:' + item.nick + '</div>';
            document.write(str);
        })
    }
})

❗jQuery有什么特点?

  • 链式编程/链式语法(即对发生在同一个JQuery对象上的一组动作,可以直接通过…连写无需要重复获取对象。更加简洁优雅)
  • CSS选择器($(“.nav”)元素/class/id/过滤选择器等)
  • 事件处理、动画设计和Ajax交互(事件处理:onload/click/mouseenter/blur等;动画:slideDown/slideUp,hide/show,fadeIn/fadeOut等)
  • DOM操作的封装(节点:append/remove/clone/parent/find/next等)
  • 插件扩展机制和丰富的插件(第三方插件:树形菜单、日期控件、图片切换插件等)
  • 兼容各种主流浏览器
  • 轻量级的js框架

❗jQuery怎么获取DOM元素

通过jQuery选择器$,元素选择器,ID选择器,类选择器来查找元素

❗jQuery里面要扩展插件一般可以怎么做?

jQuery里面有一个API的,比如想写一个类似于Vue那种指令的东西

第一种:给jQuery类本身添加方法$.extend()

$.extend({
	foo:function(){
		alert("foo");
	},
	bar:function(){
		alert("bar");
	}
})
//调用方法 
$.foo();
$.bar();

第二种:给jQuery对象添加方法$.fn.extend()

$.fn.foo = function(){
	alert("hello jquery");
}
$('#myF').foo()

jQuery.extend()是为类添加类方法(静态方法),需要通过jQuery类来调用(或直接$.XXX调用);
jQuery.fn.extend()是为jQuery类添加成员函数(实例方法),所有jQuery实例都可以直接调用(需要使用$().XXX调用)

❗jQuery绑定事件是怎么绑定的?

比如说有bind,leve怎么绑定的,你就说on事件注册是怎么注册吧,on事件里面总共有3个参数分别是什么
第一种:$(“选择器”).事件名称(匿名函数)

//这里的button为元素选择器,click为鼠标点击事件,mouseenter为鼠标聚焦事件,mouseleave为鼠标离焦事件
$("button").click(function(){
	//函数内容
})

第二种:$(“选择器”).bind({“事件名称”:匿名函数})

//button为元素选择器,bind的中文意思为‘绑定’
$("button").bind({"click":function(){
	//函数内容
}})

第三种:
两个形参:$(“选择器”).on(“事件名称”,匿名函数)
三个形参:$(“父节点选择器”).on(“事件名称”,“孩子节点,即要绑定的元素”,匿名函数)

$("button").on("click",function(){
	//函数内容
})

$("ul").on("click","li",function(){
	$(this).css("color","blue"); //this表明当前点中的对象,此语句表明,当点击li标签时候,将该li标签颜色变为blue
})

第四种:$(“选择器”).live(“事件名称”, fn)

$("button").live({"click", function(){
	//函数内容
}})

第五种:$(“父节点选择器”).delegate(“孩子节点,即要绑定的元素”,“事件名称”,匿名函数)

$("ul").delegate("li","click",function(){
	$(this).css("color","blue");
})

❗jQuery里面设置样式怎么设置

.css('color': '#fff')

❗jQuery怎么判断div有没有显示或隐藏

❗form表单提交数据有几种方式?

1、submit提交

<!-- 如果点击提交,表单数据会被发送到名为demo_form.asp的页面,如果没有action属性,表单数据会被发送到当前页面的浏览器地址栏中显示 -->
<form action="demo_form.asp">
 First name:<input type="text" name="firstname">
    <input type="submit" value="Submit">
</form>

2、ajax提交

❗ECharts你有了解吗?

使用:
①实例化对象init;②指定配置和数据;③配置项和数据给我们的实例化对象。

回答:我做一个折线图,改一下上面的label,改变颜色啦这些

【Git】

Git怎么使用?

Git常用的是以下 6 个命令:git clone、git push、git add、git commit、git checkout、git pull
创建仓库命令:
git init初始化仓库
git clone 粘贴仓库地址 拷贝一份远程仓库,也就是下载一个项目
提交与修改:
git add .添加文件到暂存区
git status查看仓库当前的状态,显示有变更的文件
git diff比较文件的不同,即暂存区和工作区的差异
git commit 提交暂存区到本地仓库
git reset回退版本
git rm删除工作区文件
git mv移动或重命名工作区文件
提交日志:
git log查看历史提交记录
git blame <file>以列表形式查看指定文件的历史修改记录
远程操作:
git remote远程仓库操作
git fetch从远程获取代码库
git pull 粘贴仓库地址下载远程代码并合并
git push上传远程代码并合并
分支管理:
git branch (branchname)创建分支
git checkout (branchname)切换分支
git merge合并分支
git branch -d (branchname)删除分支

git冲突怎么解决

在文件中手动去修改它。用git addgit commit再提交一次

❗git如果你commit了一个信息写错了,你怎么进行修改?

步骤1. 输入git commit --amend命令
随后,进入vim命令窗口
步骤2. 按i,在#的最上方删掉错误的描述,然后重新输入注释。
步骤3. 按 Esc 按钮退出编辑模式,按 :wq 键,保存并退出即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值