前端面试练习24.3.7

目录

1.类型转换练习

2.数据之间运算

算术运算

比较运算

逻辑运算

3.动态执行JS(类似eval方法)

1.eval()方法

2.setTimeout

3.创建DOM节点进行添加

4.Function的最后一个参数当作函数体直接运行

4.promise工具函数练习

5.统计字符频率写法的发散思维

6.深拷贝和浅拷贝

深拷贝的一些方法

手动递归赋值

JSON的序列化与反序列化

第三方的库(略)


1.类型转换练习

对象转原始类型

1.先调用对象的valueOf方法,如果返回原始类型,则直接返回

2.如果valueOf返回的不是原始类型,则调用toString方法,如果返回原始类型,则直接返回

3.如果toString返回的不是原始类型,则报错

原始转字符串

例子:

  • String(null)'null'
  • String(undefined)'undefined'
  • String(123)'123'
  • String(true)'true'
  • String(true)'false'

原始转数字

  • Number(true)1
  • Number(false)0
  • Number(null)0
  • Number(undefined)NaN
  • Number('\n')0
  • Number('123')123
  • Number('123abc')NaN

所有转Boolean

记住为false的

  • Boolean(null)false
  • Boolean(undefined)false
  • Boolean(0)false
  • Boolean('')false
  • Boolean(NaN)false
// 定义所有的JS类型
let str = 'asdf'
let num = 123
let bool = true
let und = undefined
let nul = null

let obj = {}
let arr = []


//JS类型转换规则
// 对象转原始类型
// 1.先调用对象的valueOf方法,如果返回原始类型,则直接返回
// 2.如果valueOf返回的不是原始类型,则调用toString方法,如果返回原始类型,则直接返回
// 3.如果toString返回的不是原始类型,则报错

// 原始转对象,不修改方法
const fun0 = () => {
  console.log(obj.valueOf(), obj.toString()) // [object Object],'[object Object]';
  console.log('obj->str', String(obj), String(obj.valueOf()), String(obj.toString())) // '[object Object]', '[object Object]', '[object Object]'
  console.log('obj->number', Number(obj), Number(obj.valueOf()), Number(obj.toString())) // NaN,NaN,NaN
}

// 原始转对象,修改 valueOf 方法
const fun1 = () => {
  obj = {
    valueOf: function () {
      return 1
    }
  }
  console.log('obj->number', Number(obj), Number(obj.valueOf()), Number(obj.toString())) // 1,1,NaN
}
// 原始转对象,修改 valueOf 和 toString 方法
const fun2 = () => {
  obj = {
    valueOf: function () {
      return {}
    },
    toString: function () {
      return 1
    }
  }
  console.log('obj->number', Number(obj), Number(obj.valueOf()), Number(obj.toString())) // 1,NaN,1
}
// 原始转对象,修改 valueOf 和 toString 方法
const fun3 = () => {
  obj = {
    valueOf: function () {
      return {}
    },
    toString: function () {
      return {}
    }
  }
  console.log('obj->number', Number(obj), Number(obj.valueOf()), Number(obj.toString())) // 报错
}
fun1()
fun2()
fun3()


// 其他的转换
const other_change = () => {
  // 原始转字符串
  console.log(String(null), String(undefined), String(123), String(true)); // 'null','undefined','123',true

  // 原始转数字
  console.log('bool->number', Number(true), Number(false)) // 1,0
  console.log('null/undefined->number', Number(null), Number(undefined));// 0,NaN
  console.log('str->number', Number('\n'), Number('123'), Number('123abc'));// 0,123,NaN

  // 所有转bool
  console.log(Boolean(null), Boolean(undefined), Boolean(0), Boolean(''), Boolean(NaN)) // false,false,false,false,false
}

// other_change()

2.数据之间运算

算术运算

+,-, *, /, %, ++, --

规则:必须是原始数据类型

1.转换为数字然后运算

2.x+y其中一方是字符串,则都转换为字符串然后拼接

3.NaN和任何类型算术运算都得到NaN

比较运算

1.>,<,>=,<=,双方转原始

1.1转数字比较

1.2都是字符串,比较字典顺序

1.3两边存在NaN为false

2.===

2.1.类型和值必须相同

2.2两端存在NaN一定返回false

3.==

3.1两端类型相同比较值

3.2都是原始类型 转换成数字比较

3.3原始和对象,对象转原始,再都转数字

3.4undefined和null只有相互比较或是自身比较才返回 true

4.5两端存在NaN一定返回false

4.!= !== 相等取反

逻辑运算

!,&&, ||, ?:

转换为Boolean,然后比较

3.动态执行JS(类似eval方法)

1.eval()方法

同步执行,打印当前作用域

var a =1
const fun1 = (code)=>{
  var a =2
  eval(code)
}

fun1('console.log("a",a)') // a 2
console.log('你好');
// 2 ,你号

2.setTimeout

异步,全局作用域

var a =1
const fun1 = (code)=>{
  var a =2
  setTimeout(code)
}

fun1('console.log("a",a)') // a 1
console.log('你好');
//  你好,a 1

3.创建DOM节点进行添加

同步方法,全局作用域,弊端产生一个元素

var a =1
const fun1 = (code)=>{
  var a =2
  const script = document.createElement('script')
  script.innerHTML = code
  document.head.appendChild(script)
}

fun1('console.log("a",a)') // a 1
console.log('你好');
//  a 1 你好

 

4.Function的最后一个参数当作函数体直接运行

同步方法,全局作用域

var a =1
const fun1 = (code)=>{
  var a =2
  new Function(code)()
}

fun1('console.log("a",a)') // a 1
console.log('你好');
//  a 1 你好

4.promise工具函数练习

 promise的标准有PromiseA+和官方ES Promise

"thenable" 对象是指具有 then 方法的对象。

一个符合规范的 then 方法需要遵循以下要求:

  1. 它是一个函数,接受两个参数:onFulfilledonRejected,都是可选的回调函数。
  2. 当 Promise 状态变为 fulfilled 时,then 方法应该调用 onFulfilled 回调函数。
  3. 当 Promise 状态变为 rejected 时,then 方法应该调用 onRejected 回调函数。
  4. then 方法应该返回一个新的 Promise 对象。
// 定义 Promise.prototype.catch 方法,用于捕获 Promise 链中的错误
Promise.prototype.catch = function (onRejected) {
  // 返回一个新的 Promise 对象,通过调用 then 方法,指定 onRejected 回调函数
  return this.then(undefined, onRejected)
}

// 定义一个函数,用于判断一个对象是否类似于 Promise
const isPromiseLike = function (obj) {
  // 如果对象存在且具有 then 方法,则认为它类似于 Promise
  return obj && typeof obj.then === 'function'
}

// 定义 Promise.prototype.resolve 方法,用于创建一个已解决的 Promise 对象
Promise.prototype.resolve = function (value) {
  // 如果 value 已经是 Promise 对象,则直接返回
  if (value instanceof Promise) return value
  // 如果 value 类似于 Promise 对象,则返回一个新的 Promise 对象,并使用 value 的 then 方法
  if (isPromiseLike(value)) {
    return new Promise((resolve, reject) => {
      value.then(resolve, reject)
    })
  }
  // 如果 value 是普通值,则返回一个已解决的 Promise 对象
  return new Promise(resolve => resolve(value))
}

// 定义 Promise.prototype.reject 方法,用于创建一个已拒绝的 Promise 对象
Promise.prototype.reject = function (reason) {
  // 返回一个新的 Promise 对象,立即执行 reject 函数,将 reason 作为拒绝的原因
  return new Promise((resolve, reject) => {
    reject(reason)
  })
}

5.统计字符频率写法的发散思维

简单类型的题目

一般写法

let str = 'qqwweqrqrqrqrqrqrqrsdvavsbbsavfGHSHJJMFJ'

const my_sort = (str)=>{
  str = str.split('')
  str = str.sort((a,b)=>a>b ? 1: a===b ? 0 : -1)
  return str
}

const fun1 = (str) => {
  let res = {}
  str = my_sort(str)
  for (let i = 0; i < str.length; i++) {
    if (res[str[i]]) {
      res[str[i]]++
    } else {
      res[str[i]] = 1
    }
  }
  return res
}
console.log(fun1(str))

独特写法

let str = 'qqwweqrqrqrqrqrqrqrsdvavsbbsavfGHSHJJMFJ'

const my_sort = (str)=>{
  str = str.split('')
  str = str.sort((a,b)=>a>b ? 1: a===b ? 0 : -1)
  return str
}

const fun2 = (str)=>{
  str = my_sort(str)
  let res = [...str].reduce((r,cur)=> (r[cur]++ || (r[cur] = 1),r),{})
  return res
}
console.log(fun2(str))

6.深拷贝和浅拷贝

知识点:

1.基本数据类型的赋值属于深拷贝,数据内容直接存放在栈中,赋值时直接是数据内容的给予

2.引用数据类型一般方法都属于浅拷贝

赋值时,新的对象获取到的是原对象存放在栈中的是一个指针,真实的数据内容是储存在堆中,栈中的指针指向队中的数据对应的地址。

所以修改新对象的值时,其实修改的是他们公共的堆内存的数据

 

所以为了一些不必要的错误,我们可以通过 

创建一个新的对象,遍历需要克隆的对象,将需要克隆对象的属性依次添加到新对象上,返回新对象。这种方式进行引用数据类型的深拷贝。

深拷贝的一些方法

手动递归赋值

function deepCopy(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }

  const newObj = Array.isArray(obj) ? [] : {};

  for (let key in obj) {
    newObj[key] = deepCopy(obj[key]);
  }

  return newObj;
}

JSON的序列化与反序列化

let originalObject = { a: 1, b: { c: 2 } };
let deepCopyObject = JSON.parse(JSON.stringify(originalObject));

第三方的库(略)

  • 19
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序猿online

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值