Open dashengzi66 opened 3 years ago
contact
const originArray = [1,2,3,4,5];
const cloneArray = originArray.concat();
console.log(cloneArray === originArray); // false
cloneArray.push(6); // [1,2,3,4,5,6]
console.log(originArray); [1,2,3,4,5];
总结:concat 只是对数组的第一层进行深拷贝
slice
const originArray = [1,2,3,4,5];
const cloneArray = originArray.slice();
console.log(cloneArray === originArray); // false
cloneArray.push(6); // [1,2,3,4,5,6]
console.log(originArray); [1,2,3,4,5];
总结:slice 只是对数组的第一层进行深拷贝
Object.assign()
let obj = {
'name': 'zs',
'age': '18'
}
let obj2=Object.assign({},newObj)
总结:Object.assign() 拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值
... 展开运算符
const originArray = [1,2,3,4,5,[6,7,8]];
const originObj = {a:1,b:{bb:1}};
const cloneArray = [...originArray];
cloneArray[0] = 0;
cloneArray[5].push(9);
console.log(originArray); // [1,2,3,4,5,[6,7,8,9]]
const cloneObj = {...originObj};
cloneObj.a = 2;
cloneObj.b.bb = 2;
console.log(originObj); // {a:1,b:{bb:2}}
总结:... 实现的是对象第一层的深拷贝。后面的只是拷贝的引用值
function intersection(...arrays) {
const len = arrays.length
if(len < 2){
return len ? arrays[0] : []
}
let result = arrays.shift()
console.log(result)
arrays.forEach(arr => {
result = result.filter(item => arr.includes(item))
})
return result
}
const arr1 = [1,2,3,4,5]
const arr2 = [4,2,1,5,6,7]
const arr3 = [2,4,7,8,3]
// 输出 [2,4]
console.log(intersection(arr1,arr2,arr3))
// 数组去重 let arr = [1, 1, 2, 3]; let unique = [... new Set(arr)];
let a = new Set([1, 2, 3]); let b = new Set([4, 3, 2]);
// 并集 let union = [...new Set([...a, ...b])]; // [1,2,3,4]
// 交集 let intersect = [...new Set([...a].filter(x => b.has(x)))]; [2,3]
// 差集 let difference = Array.from(new Set([...a].filter(x => !b.has(x)))); [1]
指触发事件后,在 n 秒内函数只能执行一次,如果触发事件后在 n 秒内又触发了事件,则会重新计算函数延执行时间
// 第一版(最简易版)
function debounce(func, wait) {
var timeout;
return function () {
clearTimeout(timeout)
timeout = setTimeout(func, wait);
}
}
//第二版(解决this和event)
function debounce(func, wait) {
var timeout;
return function () {
var context = this;
var args = arguments;
clearTimeout(timeout)
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
//第三版(立即执行版)
function debounce(func, wait, immediate) {
var timeout;
return function () {
var context = this;
var args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
// 如果已经执行过,不再执行
var callNow = !timeout;
timeout = setTimeout(function(){
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}
//大裤衩版
function debounce(func, wait, immediate) {
let timeout, args, context, timestamp, result
const later = function() {
// 据上一次触发时间间隔
const last = +new Date() - timestamp
// 上次被包装函数被调用时间间隔 last 小于设定时间间隔 wait
if (last < wait && last > 0) {
timeout = setTimeout(later, wait - last)
} else {
timeout = null
// 如果设定为immediate===true,因为开始边界已经调用过了此处无需调用
if (!immediate) {
result = func.apply(context, args)
if (!timeout) context = args = null
}
}
}
return function(...args) {
context = this
timestamp = +new Date()
const callNow = immediate && !timeout
// 如果延时不存在,重新设定延时
if (!timeout) timeout = setTimeout(later, wait)
if (callNow) {
result = func.apply(context, args)
context = args = null
}
return result
}
}
Function.prototype.bind2 = function (context){
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
return self.apply(this instanceof fNOP ? this : context, args.concat(bindArgs));
}
fNOP.prototype = this.prototype;
fBound.prototype = new fNOP();
return fBound;
}
let a = 10+null+true+[]+undefined+'珠峰'+null+[]+10+false console.log(a) // '11undefined珠峰null10false'
由于我们可以肆意修改原型的指向,所以检测出来的结果是不准确的
//实例.proto === 类.prototype
function instance_of(example,classFunc){
let classFuncPrototype = classFunc.prototype,
proto = Object.getPrototypeOf(example);//example.proto
while(true){
if(proto === null){
//Object.prototype.proto ==> null
return false
}
if(proto == classFuncPrototype){
//查找过程有,则证明实例是这个类的一个实例
return true
}
proto = Object.getPrototypeOf(proto)
}
}
let arr=[]; console.log(instance_of(arr,Array)); console.log(instance_of(arr,RegExp)); console.log(instance_of(arr,Object));
(function () {
var class2type = {};
var toString = class2type.toString; //=>Object.prototype.toString
// 设置数据类型的映射表
["Boolean", "Number", "String", "Function", "Array", "Date", "RegExp", "Object", "Error", "Symbol"].forEach(
name => {
class2type[`[object ${name}]`] = name.toLowerCase();
})
console.log(class2type)
function toType(obj) {
// 传递的值是null或者undefined,就返回对应的字符串
if (obj == null) {
return obj + "";
}
// 基本数据类型采用typeof检测
return typeof obj === "object" || typeof obj === "function" ?
class2type[toString.call(obj)] || "object" :
typeof obj;
}
window.toType = toType;
})()
Array.prototype.forEach = function forEach(callback, context) { // this -> arr let self = this, i = 0, len = self.length; context = context == null ? window : context; for (; i < len; i++) { console.log(1) typeof callback === 'function' ? callback.call(context, self[i], i) : null; } } let arr = new Array(10).fill(0) arr.forEach((item,i)=>{ console.log(item); })
async function async1() { console.log("async1 start"); await async2(); console.log("async1 end"); } async function async2() { console.log("async2"); } async1(); setTimeout(() => { console.log("timeout"); }, 0); new Promise(function (resolve) { console.log("promise1"); resolve(); }).then(function () { console.log("promise2"); });
MVVM 定义:MVVM是Model-View-ViewModel的简写,即模型-视图-视图模型【模型】指的是指的是后端传递的数据,视图】指的是所看到的页面。【视图模型】mvvm模式的核心,它是连接view和model的桥梁。它有两个方向:一是将【模型】转化成【视图】,即将后端传递的数据转化成所看到的页面。实现的方式是:数据绑定。二是将【视图】转化成【模型】,即将所看到的页面转化成后端的数据。实现的方式是:DOM 事件监听。这两个方向都实现的,我们称之为数据的双向绑定。
总结:在MVVM的框架下视图和模型是不能直接通信的。它们通过ViewModel来通信,ViewModel通常要实现一个observer观察者,当数据发生变化,ViewModel能够监听到数据的这种变化,然后通知到对应的视图做自动更新,而当用户操作视图,ViewModel也能监听到视图的变化,然后通知数据做改动,这实际上就实现了数据的双向绑定。并且MVVM中的View 和 ViewModel可以互相通信。MVVM流程图如下:
vue是采用Object.defineProperty的getter和setter,并结合观察者模式来实现数据绑定的。当把一个普通的javascript对象传给Vue实例来作为它的data选项时,Vue将遍历它的属性,用Object.defineProperty将它们转为getter/setter。用户看不到getter/setter,但是在内部它们让Vue追踪依赖。在属性被访问和修改时通知变化。
Observer 数据监听器,能够对数据对象的所有属性进行监听,如有变动可拿到最新的值并通知订阅者,内部采用Obiect.defineProperty的getter和setter来实现。
Complie指令解析器,它的作用对每个元素节点的指令进行扫描和解析,根据指令模板替换数据,以及绑定Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应的回调函数
Watcher订阅者,作为连接Observer和Complie的桥梁,能够订阅并收到每个属性变动的通知,执行指令绑定的相应回调函数。 Dep消息订阅器,内部维护了一个数组,用来收集订阅者(watcher),数据变动触发notify函数,再调用订阅者的update方法。
从图中可以看出,当执行 new Vue() 时,Vue就是进入了初始化阶段,一方面Vue会遍历data选项中的属性,并且Object.defineProperty将它们转换为getter/setter,实现数据变化监听功能;Vue的指令编译器Compile对元素节点的指令进行扫描和解析,初始化视图,并订阅Wacther来更新视图,此时wather会将自己添加到消息订阅器(Dep),初始化完毕。
当数据发生变化时,Observer中的setter方法被触发,setter会立即调用Dep。Dep开始遍历所有的订阅者,并调用订阅者的update方法,订阅者收到通知后对视图进行相应更新
什么是Virtual DOM 定义: 就是用一个原生的 JS 对象去描述一个 DOM 节点 好处: 1.将真实元素节点抽象成 VNode,有效减少直接操作 dom 次数,从而提高程序性能 2.方便实现跨平台
父子组件通信
语义标签 example 增强型表单 视频和音频 Canvas绘图 SVG绘图 地理定位 拖放API WebWorker WebStorage WebSocket
1.使用Vue.extend()创建一个组件 2.使用Vue.component()方法注册组件 3.如果子组件需要数据,可以在props中接受定义 4.子组件修改好数据之后,想把数据传递给父组件,可以使用emit()方法
1.存储地方不同 vuex 存储在内存(vuex 属于js,因此vuex使用的数据自然会放在内存),localstorage则以文件的形式存储在本地 localStorage和sessionStorage只能存储字符串类型,对于复杂的对象可以使用ECMAScript提供的JSON对象的stringify和parse来处理
2.应用场景不同 vuex用于组件之间的传值(app大部分都是由单页面组件组成),localstorage,sessionstorage则主要用于不同页面之间的传值。
3.永久性:当刷新页面(这里的刷新页面指的是 --> F5刷新,属于清除内存了)时vuex存储的值会丢失,sessionstorage页面关闭后就清除掉了,localstorage不会。
请找出字符串中连续出现最多的字符和个数
去重思维
排序
从最大到最小去试找