自己回答:
基础类型里:
常见的类型转换有:
强制转换(显示转换):我们很清楚看见发生类型转换,常见的方法有:
自动转换(隐式转换):
==
、!=
、>
、<
)、if
、while
需要布尔值的地方+
、-
、*
、/
、%
)1、自动转换为布尔值
在需要布尔值的地方,将非布尔值转为布尔值,比如if,while
false
,其他转成true
2、自动转换为字符串
遇到预期为字符串的地方,就会将非字符串的值自动转为字符串
常发生在+运算中,一旦存在字符串,就会进行字符串拼接操作
'5' + 1 // '51'
'5' + true // "5true"
'5' + false // "5false"
'5' + {} // "5[object Object]"
'5' + [] // "5"
'5' + function (){} // "5function (){}"
'5' + undefined // "5undefined"
'5' + null // "5null"
3、自动转换成数值
除了+
有可能转为字符串,其他运算符转成数值
'5' - '2' // 3
'5' * '2' // 10
true - 1 // 0
false - 1 // -1
'1' - 1 // 0
'5' * [] // 0
false / '5' // 0
'abc' - 1 // NaN
null + 1 // 1
undefined + 1 // NaN
null转为数值时,值为0,undefined转为数值时,值为NaN
自己回答:
基础数据存在栈里,引用类型存在堆里,引用类型的地址存在栈里,深拷贝和浅拷贝是对于引用类型来说,深拷贝是将堆里的数据拷贝一份,浅拷贝是拷贝引用类型存在栈里的地址,新旧地址指向同一个堆数据
实现:
最常用 JSON.parse(JSON.stringify(obj))
或者遍历循环赋值
基本类型数据保存在栈内存中,引用类型数据保存在堆内存中,引用数据类型的变量是一个指向堆内存中实际对象的引用,存在栈中。
浅拷贝: 创建新数据,这个数据有原始数据属性值的一份精确拷贝
如果属性是基本类型,拷贝的就是基本类型的值。如果属性是引用类型,拷贝的就是内存地址。即浅拷贝是拷贝一层
,深层次的引用类型则共享内存地址
实现浅拷贝:
function shallowClone(obj) {
const newObj = {};
for(let prop in obj) {
if(obj.hasOwnProperty(prop)){
newObj[prop] = obj[prop];
}
}
return newObj;
}
在javaScript中,存在浅拷贝的现象有:
深拷贝:
深拷贝开辟一个新的栈,两个对象属性完全相同,但是对应两个不同的地址,修改一个对象的属性,不会改变另一个对象的属性
常见的深拷贝对象有:
区别:
浅拷贝和深拷贝都是创建一个新的对象,但是在复制对象属性的时候,行为就不一样,浅拷贝只复制属性指向某个对象的指针,而不是复制对象本身,新旧对象还是共享同一颗内存,修改对象属性会影响原对象
const obj1 = {
name : 'init',
arr : [1,[2,3],4],
arr2: [1,[2,3],4],
};
const obj3=shallowClone(obj1) //
obj3.name = "update";
obj3.arr[1] = [5,6,7] ; //
console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 5, 6, 7 ],4 ], arr2: [ 1, [3,4,2],4 ] }
console.log('obj3',obj3) // obj3 { name: 'update', arr: [ 1, [ 5, 6, 7 ],4 ], arr2: [ 1, [3,4,2],4 ] }
const obj2=obj1
obj2.name = "222";
obj2.arr2[1] = [3,4,2] ; // obj2 { name: '222',, arr: [ 1, [ 5, 6, 7 ],4 ], arr2: [ 1, [3,4,2],4 ] }
console.log('obj2',obj2)
赋值的话不管改变的是基础类型还是引用类型,新数据的改变都会影响原数据,浅拷贝拷贝了一层,基础数据不会变
深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
// 深拷贝
const obj1 = {
name : 'init',
arr : [1,[2,3],4],
};
const obj4=deepClone(obj1) //
obj4.name = "update";
obj4.arr[1] = [5,6,7] ; //
console.log('obj1',obj1) // obj1 { name: 'init', arr: [ 1, [ 2, 3 ], 4 ] }
console.log('obj4',obj4) // obj4 { name: 'update', arr: [ 1, [ 5, 6, 7 ],
4 ] }
小结:
拷贝类型是引用类型的情况下:
自己回答:
函数缓存?
函数缓存,就是函数运算过的结果进行缓存
本质就是用空间(缓存存储)换时间(计算过程)
常用于缓存数据计算结果和缓存对象
const add = (a,b) => a+b;
const calc = memoize(add); // 函数缓存
calc(10,20);// 30
calc(10,20);// 30 缓存
缓存只是一个临时的数据存储,它保存数据,以便将来对该数据的请求能够更快地得到处理
如何实现
实现函数缓存主要依靠闭包、柯里化、高阶函数,这里再简单复习下:
闭包: 函数+函数体内可访问的变量总和
(function() {
var a = 1;
function add() {
const b = 2
let sum = b + a
console.log(sum); // 3
}
add()
})()
add
函数本身,以及其内部可访问的变量,即 a=1
,这两个组合在一起就形成了闭包
柯里化:
把接受多个参数的函数转换成接受一个单一参数的函数
// 非函数柯里化
var add = function (x,y) {
return x+y;
}
add(3,4) //7
// 函数柯里化
var add2 = function (x) {
//** **
return function (y) {
return x+y;
}
}
add2(3)(4) //7
将一个二元函数拆分成两个一元函数
高阶函数:
通过接收其他函数作为参数或返回其他函数的函数
function foo(){
var a = 2;
function bar() {
console.log(a);
}
return bar;
}
var baz = foo();
baz();//2
函数foo
返回另一个函数bar,baz持有对foo中定义的bar函数的引用,由于闭包特性,a的值能够得到。
开始实现函数函数。原理:把参数和对应的结果数据存在一个对象中,调用时判断参数对应的数据是否存在,存在就返回对应结果,否则就返回计算结果
const memoize = function (func, content) {
let cache = Object.create(null)
content = content || this
return (...key) => {
if (!cache[key]) {
cache[key] = func.apply(content, key)
}
return cache[key]
}
}
const calc = memoize(add);
const num1 = calc(100,200)
const num2 = calc(100,200) //缓存得到的结果
过程分析:
cache
cache
中。如果已经存在,直接返回 cache
的内容,如果没有存在,使用函数 func
对输入参数求值,然后把结果存储在 cache
中应用场景:
虽然使用缓存效率非常高,但并不是所有场景都适用
以下几种情况,适合使用缓存:
自己回答:string:chart、splitte、slite、
1、增
2、删
这三个都返回一个子字符串,都接收一或两个参数
let stringValue = "hello world";
console.log(stringValue.slice(3)); // "lo world"
console.log(stringValue.substring(3)); // "lo world"
console.log(stringValue.substr(3)); // "lo world"
console.log(stringValue.slice(3, 7)); // "lo w"
console.log(stringValue.substring(3,7)); // "lo w"
console.log(stringValue.substr(3, 7)); // "lo worl"
3、改
4、查
5、转化(字符转数组)
let str = "12+23+34"
let arr = str.split("+") // [12,23,34]
6、模板匹配方法
match:接收一个参数,可以是正则表达字符串,也可以是RegExp对象(提供正则表达式),返回匹配的数组
let text = "cat, bat, sat, fat";
let pattern = /.at/;
let matches = text.match(pattern);
console.log(matches[0]); // "cat"
search:接收一个参数,可以是正则表达字符串,也可以是RegExp对象(提供正则表达式),返回匹配索引
let text = "ca3t, bat, sat, fat";
let pos = text.search(/at/);
console.log(pos); // 7
replace、replaceAll:接收两个参数,第一个参数为匹配的内容,第二个参数为替换的元素
let text = "cat, bat, sat, fat";
let result = text.replace("at", "ond");
console.log(result); // "cond, bat, sat, fat"
let resultall = text.replaceAll("at", "ond");
console.log(resultall); // "cond, bond, sond, fond"
自己回答:foreach、map、find、inclued、fitter、concat、push、pop、shift、unshift、join、flat、
分为