记录有如下问题
// 1. 判断对象是否为空
// 2. typeof 返回值有哪些
// 3. typeof 和 instanceOf的区别
// 4. 深拷贝、浅拷贝
// 5. 获取一个字符串的后十位
// 6. lodash 性能问题
// 7. 空对象和空数组 的布尔类型
// 8. 判断一个变量是否为数组或者对象
// 9. 前端如何设置cookie,让别人无法读取?
1. 判断对象是否为空
const data = {};
const result = JSON.stringify(data) === '{}';
console.log('result', result); // === true
class Person {
state = {};
}
Person.prototype.getting = function () {
console.log('1', 1);
};
const p1 = new Person();
console.log('p1', p1);
console.log('p1', JSON.stringify(p1) === '{}');
// p1 Person {}
// p1 false
// ---
for (let key in p1) {
console.log('key:', key);
// key: state
// key: getting
}
for (const key of Object.keys(p1)) {
// Object.key: state
console.log('Object.key:', key);
}
console.log('Object.getOwnPropertyNames(p1):', Object.getOwnPropertyNames(p1));
// Object.getOwnPropertyNames(p1): [ 'state' ]
2. typeof 返回值有哪些
console.log('typeof true ===', typeof true);
console.log('typeof undefined === ', typeof undefined);
console.log('typeof "a" === ', typeof 'a');
console.log('typeof 1 === ', typeof 1);
console.log('typeof null === ', typeof null);
console.log('typeof {} === ', typeof {});
console.log('typeof [] === ', typeof []);
console.log('typeof function() {} === ', typeof function () {});
console.log('typeof class A {} ===', typeof class A {});
console.log('typeof new Set() === ', new Set());
console.log('typeof new Map() === ', new Map());
console.log('typeof Symbol() === ', Symbol());
console.log('typeof Date ===', typeof Date);
console.log('typeof new Date() ===', typeof new Date());
const test1 = Symbol(1);
const test2 = Symbol(1);
console.log('test1 === test2', test1 === test2); // false
// typeof true === 'boolean'
// typeof undefined === 'undefined'
// typeof "a" === 'string'
// typeof 1 === 'number'
// typeof null === 'object'
// typeof {} === 'object'
// typeof [] === 'object'
// typeof function() {} === 'function'
// typeof class A {} === 'function'
// typeof new Set() === 'object'
// typeof new Map() === 'object'
// typeof Symbol() === 'symbol'
// typeof Date === 'function'
// typeof new Date() === 'object'
console.log('typeof new Set() === "object"', typeof new Set() === 'object'); // true
3. typeof 和 instanceOf的区别
// typeof 和 instanceof的区别
// 1. typeof 是xxx的类型
// instanceof 是xxx的实例
// 2. typeof 的返回值有"number","boolean","string","function","object","undefined"
// instanceof 返回值是 true OR false
// 3. typeof(X) X可以不定义,但是不会报错,返回值是"undefined"字符串
// instanceof 左边的值必须先定义,右边必须为对象或者function否则会报错
// 4. instanceof 可以对不同的对象实例进行判断,
// 判断的方法是根据对象的原型链一次向下查询
// 如果原型链存在那么 返回true 否则返回false
// 5. instanceof 返回的值true false 在特殊情况下不可靠
// 原因是 instance可以被自定义
// 这个在 es6 阮一峰老师的书上有讲到
// 具体这么写:
// class PersonInstance {
// // 直接对PersonInstance使用 instanceof 时被调用
// static [Symbol.hasInstance](x) {
// return typeof x === 'xxx';
// }
// // 对PersonInstance实例 使用instanceof时被调用
// [Symbol.hasInstance](y) {
// return typeof y === 'xxxx';
// }
// }
class PrimitiveString {
static [Symbol.hasInstance](x) {
console.log('x: ', x); // x: hello
return typeof x === 'string';
}
}
console.log(
'"hello" instanceof PrimitiveString',
'hello' instanceof PrimitiveString
); // true
// hasInstance是 可以自定义 instanceof行为
class PrimitiveString2 {
// 静态方法
static [Symbol.hasInstance](x) {
console.log('x: ', x); // x: hello
return typeof x === 'object';
}
// 实例访问的方法
[Symbol.hasInstance](y) {
console.log('y', y); // hello2
return typeof y === 'hello';
}
}
console.log(
'"hello" instanceof PrimitiveString2',
{} instanceof PrimitiveString2
); // true
console.log(
'"hello" instanceof PrimitiveString2',
'hello' instanceof PrimitiveString2
); // false
console.log(
'"hello2" instanceof new PrimitiveString2()',
'hello2' instanceof new PrimitiveString2()
); // false
console.log(
'"hello" instanceof new PrimitiveString2()',
'hello' instanceof new PrimitiveString2()
); // true
// ----
console.log('p1 instanceof Person:', p1 instanceof Person);
// p1 instanceof Person: true
console.log('p1 instanceof PrimitiveString2:', p1 instanceof PrimitiveString2);
// p1 instanceof PrimitiveString2: true
// 说明 instanceof 不是百分百准确的
4. 深拷贝(考虑Date, RegExp, Error)、浅拷贝
function deepCopy(obj, cache = []) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
const objType = Object.prototype.toString.call(obj).slice(8, -1);
// 考虑 正则对象的copy
if (objType === 'RegExp') {
return new RegExp(obj);
}
// 考虑 Date 实例 copy
if (objType === 'Date') {
return new Date(obj);
}
// 考虑 Error 实例 copy
if (objType === 'Error') {
return new Error(obj);
}
const hit = cache.filter((c) => c.original === obj)[0];
if (hit) {
return hit.copy;
}
const copy = Array.isArray(obj) ? [] : {};
cache.push({original: obj, copy});
Object.keys(obj).forEach((key) => {
copy[key] = deepCopy(obj[key], cache);
});
return copy;
}
// JSON.parse(JSON.stringify())
// 1. 循环引用的问题,会直接报错
// 2. 函数,undefined,则序列化的结果会把函数或 undefined丢失
// 3. RegExp、Error对象会被转换成'{}'空对象
// 4. 如果obj里面有时间对象,则JSON.stringify后再JSON.parse的结果,时间将只是字符串的形式。而不是时间对象;
// 5. 如果obj里有NaN、Infinity和-Infinity,则序列化的结果会变成null
// 6. JSON.stringify()只能序列化对象的可枚举的自有属性,
// 例如 如果obj中的对象是有构造函数生成的,
// 则使用JSON.parse(JSON.stringify(obj))深拷贝后,
// 会丢弃对象的constructor;
// 7. 原型链丢失
//
// 浅拷贝
// 1. Object.assign({a: 1}, {b: 1}, {c: 1}) === "{a: 1, b: 1, c: 1}"
// 2. 可扩展运算符 [...[{}, {}]], {...{a: 1, b: 1}}
// 3. 数组的 concat, slice 返回值
// 4. 函数参数赋值((obj) => console.log(obj))(myobj)
// 5. 数组,对象的解构赋值等
5. 获取一个字符串的后十位
主要时slice方法的熟练程度
// str = '012345678954321';
// str.slice(-10); // => '5678954321'
6. lodash 性能问题
7. 空对象和空数组 的布尔类型
console.log('null == false', null == false); // flase
console.log('[] == false', [] == false); // true
console.log('{} == false', {} == false); // false
console.log(`[] + ''`, [] + ''); // ''
console.log(`{} + ''`, {} + ''); // [object Object]
8. 判断一个变量是否为数组或者对象
// Object.prototype.toString.call({})
// "[object Object]"
// Object.prototype.toString.call([])
// "[object Array]"
// Object.prototype.toString.call(null)
// "[object Null]"
// Object.prototype.toString.call(undefined)
// "[object Undefined]"
// Object.prototype.toString.call(1)
// "[object Number]"
// Object.prototype.toString.call(Number)
// "[object Function]"
// Object.prototype.toString.call(() =>{})
// "[object Function]"
// Object.prototype.toString.call('a')
// "[object String]"
// Object.prototype.toString.call(true)
// "[object Boolean]"
// Object.prototype.toString.call(new Set())
// "[object Set]"
// Object.prototype.toString.call(new Map())
// "[object Map]"
// Object.prototype.toString.call(Symbol())
// "[object Symbol]"
9. 如何设置cookie,防止前端写入
// 服务端接口设置
// http httpOnly: true
// https secure: true