美文网首页
面试题【Day08】

面试题【Day08】

作者: 小王子__ | 来源:发表于2021-09-03 17:49 被阅读0次

本篇绪论

1,Object.prototype.toString.call()方法

2,ES6函数参数解构

3,computed、methods、watch区别

1,Object.prototype.toString.call()方法

JS中使用typeof判断基础数据类型:number、string、undefined、null、boolean,对于数组、函数、对象来说都是统一返回object。这时就应该使用Object.prototype.toString.call()来精准的判断数据类型了

Object.prototype.toString.call(null)
Object.prototype.toString.call(undefined)
Object.prototype.toString.call('abc')
Object.prototype.toString.call(123)
Object.prototype.toString.call(true)
Object.prototype.toString.call(function fn () {})
Object.prototype.toString.call(new Date())
Object.prototype.toString.call([1,2,3])
Object.prototype.toString.call({name: 'xiaowang'})
image
function Person(name, age) {
  this.name = name
  this.age = age
}
let p = new Person('Rose', 18)
console.log(Object.prototype.toString.call(p))  // [object Object]
// 很明显,这种方法不能准确判断p1是Person的实例,而只能用instanceof进行判断
p instanceof Person // true

toString是Object的原型方法,而Array、function作为Object的实例,都重写了toString方法。

let arr = [1,2,3]
console.log(Array.prototype.hasOwnProperty('toString'))
console.log(arr.toString())
delete Array.prototype.toString
console.log(Array.prototype.hasOwnProperty('toString'))
console.log(arr.toString())
// hasOwnProperty 判断自身属性是否存在
image

常见面试题:实现一个函数clone,可以对js中的5种数据类型纪念性值复制

function getDataType(data){  
  var getType = Object.prototype.toString
  var myType = getType.call(data)  
  var typeName = myType.slice(8,-1)  
  var copyData='' 
  switch(typeName){  
      case 'Number': 
        copyData = data-0
        break
      case 'String': 
        copyData = "'" + data + "'"
        break 
      case 'Function': 
        copyData=data 
        break 
      case 'Null': 
        copyData=null
        break 
      case 'Undefined': 
        copyData="Undefined"
        break
      case 'Array':   
        copyData=[] 
        for(var i=0;i<data.length;i++){  
          copyData[i]=data[i]  
        }  
        break
      case 'Object': 
        copyData={}
        for(var x in data){  
          copyData[x]=data[x] 
        }  
        break
      case 'Boolean': 
        copyData=data
        break
      default : 
        copyData=data
        break
  }  
  return copyData
}   
console.log(getDataType(123))
console.log(getDataType("123"))
console.log(getDataType(null))
console.log(getDataType(undefined))
console.log(getDataType(false))
console.log(getDataType([1,2,4]))
console.log(getDataType({"name":"wc"}))
console.log(getDataType(function(){alert(23)}))
image

2,ES6函数参数解构

常规的JS,如果给函数传递的参数是一个对象,写法如下

const firstName = 'huahua'
const lastName = 'xiao'
const person = {
  firstName,
  lastName
}
console.log(person.firstName + ' ' + person.lastName  // huahua xiao

以上代码等同于:

const person = {
  firstName: firstName,
  lastName: lastName
}

ES6的解构是用来给变量赋值的

const person = {
  firstName: 'huahua',
  lastName: 'xiao'
}
const {firstName, lastName} = person
// 这里的{firstName, lastName}其实就是{firstName: firstName, lastName: lastName}
console.log(firstName + '-' + lastName)  // huahua-xiao

解构赋值可以有默认值

const {firstName = 'huahua', lastName = 'xiao'} = {}
console.log(firstName + lastName)  // huahua xiao

解构应用在函数参数传递上

function sayName({firstName, lastName} = {}) {
  console.log(firstName + ' ' + lastName)  // huahua xiao
}
sayName({firstName: 'huahua', lastName: 'xiao'}) 

传递的参数person会直接取代右边的{firstName: 'lebron'}, 然后被当作真正的解构赋值对象,从而造成firstName没有默认值:

function sayName({firstName, lastName = 'bar'} = {firstName: 'lebron'}) {
  console.log(firstName + ' ' + lastName)
}
let person = {
  wrongFirstName: 'yy',
  lastName: 'xiao'
}
sayName(person)  // undefined xiao

3,computed、methods、watch区别

模版内的表达式设计初衷是用于简单的计算。在模版中放入太多的逻辑会让模版过重且难以维护,对于复杂逻辑,vue提倡使用计算属性。

computed、methods区别

理论上,computed所有实现可以使用methods完全替换

以下示例使用computed和methods实现字符串反转

methods:

<p>reverse message: {{ reverseMessage() }}</p>
data () {
  return {
    message: 'xiaohuahua'
  }
},
methods: {
  reverseMessage () {
    return this.message.split('').reverse().join('')  // auhauhoaix
  }
}
// split('') 将字符串转为数组
// join('') 将数组转为字符串

computed:

<p>reverse message: {{ reverseMessage }}</p>
data () {
  return {
    message: 'xiaohuahua'
  }
},
computed: {
  reverseMessage () {
    return this.message.split('').reverse().join('')
  }
}

计算属性是基于响应式依赖进行缓存的。只在相关响应式依赖发生改变时它们才会重新求值。这意味着只要message还没有发生改变,多次访问reverseMessage计算属性会立即返回之前的计算结果,而不必再次执行函数,而方法却会执行

这也就意味着下面的计算属性将不再更新,因为 Date.now()不是响应式依赖

computed: {
  now () {
    return Date.now()
  }
}

打个比方,我们有一个性能开销比较大的计算属性A,它需要遍历一个巨大的数组并做大量的计算,我们可能有其他的计算属性依赖A,如果没有缓存,我们将不可避免的多次执行A的getter。

computed、watch区别

vue提供了一种更通用的方式来观察和相应Vue实例上的数据变动:侦听属性(watch)

当有一些数据需要随着其他数据变动而变动的时候,很容易滥用watch,而通常更好的做法是使用计算属性,细想一下下面的例子

<div id="demo">{{ fullName }}</div>
data () {
  return {
    firstName: 'Foo',
    lastName: 'Bar',
    fullName: 'Foo Bar'
  }
},
watch: {
  firstName: function (val) {
    this.fullName = val + ' ' + this.lastName
  },
  lastName: function (val) {
    this.fullName = this.firstName + ' ' + val
  }
}

以上代码是命令式且重复的,将它与计算属性的版本进行比较

data () {
  return {
    firstName: 'Foo',
    lastName: 'Bar'
  }
},
computed: {
  fullName () {
    return this.firstName + '' + this.lastName
  }
}

好得多了,不是吗?

相关文章

网友评论

      本文标题:面试题【Day08】

      本文链接:https://www.haomeiwen.com/subject/mkbkwltx.html