2021年3月- 杭州-阿里阿里妈妈事业群-电话面面试题
发布日期:2021-05-10 22:43:43 浏览次数:26 分类:精选文章

本文共 4479 字,大约阅读时间需要 14 分钟。

阿里妈妈事业群-电话面

判断是不是数组

Array.isArray(a)

a instanceof Array

a.constructor === Array

Object.prototype.toString.call(a) === '[object Array]'

你提到instanceof就聊一聊instanceof

Instanceof 用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。

例如在表达式 left instanceof right 中 会沿着 left 的原型链查找看是否存在 right 的 prototype 对象。

left.__proto__.__proto__... =?= right.prototype

那就说一说原型链

每一个构造函数都有一个 prototype 属性,指向了它的原型。

每一个实例有一个 __proto__ 属性,这个属性指向了它的原型,原型上还有 __proto__,指向了它父类的原型,一直到 Object.prototype 为止,所以 Object 的原型是一个对象的终极原型,它的 prototype 是 null。

访问实例的一个属性,会从它的实例内部查找,若没有就到它的原型,还没有就继续向父一级原型查找,一直找到 Object.prototype 的位置,没有就返回 undefined。

原型链怎么实现继承

假设构造函数 B() 需要继承构造函数 A(),就可以通过将函数 B() 的显式原型指向一个函数 A() 的实例,然后再对 B 的显式原型进行扩展。那么通过 function B() 创建的实例,既能访问 function B() 的属性 b,也能访问 function A() 的属性 a,从而实现了多层继承。

具体例子:

// 定义动物类  
function Animal(name) { ... }
// 原型方法
Animal.prototype.eat = function () { ... }
// 原型链继承
function Cat(food) { ... }
Cat.prototype = new Animal()
Cat.prototype.name = 'cat'

除此之外,构造继承

function Cat(name) {  
Animal.call(this)
this.name = name
}

实例继承

function Cat(name) {  
var instance = new Animal()
instance.name = name
return instance
}

通过原型链判断是不是数组

a.__proto__.__proto__... =?= Array.prototype

数组操作元素的方法

IndexOf()/lastIndexOf():返回元素在数组第一次/最后一次出现的索引,从0开始。若不存在返回-1。

slice(start, end):索引从 start 开始截取到索引 end 结束,没有参数复制整个数组。

concat():合并数组,如果参数是数组会被拉平一次再加入到新数组。

join():把当前 Array 的每个元素都用指定字符串连接起来,没有参数默认用’,'连接。

toString():返回数组的字符串形式。

valueOf():返回数组本身。

map(function(elem, index, arr)):对数组的所有成员依次调用一个函数,返回值是一个新的数组。三个参数依次是当前成员、当前位置、数组本身。

forEach():与 map 方法相似,也是遍历数组的所有成员,执行某种操作,一般没有返回值。

filter():删选,返回过滤后的新数组。

some():只要有一个数组成员的返回值为 true,则整个 some 方法的返回值就是 true,否则为 false。空数组返回 false。

every():所有数组成员的返回值都是 true 才返回 true,否则为 false。空数组返回 true。

reduce()/reduceRight():依次处理数组的每个成员,最终累计为一个值。

  • 不改变原数组的方法

push():向数组的末尾添加若干元素,返回值是改变后的数组长度。

pop():删除数组最后一个元素,返回值是删除的元素。

unshift():向数组头部添加若干元素,返回值是改变后的数组长度。

shift():删除数组第一个元素,返回值是删除的元素。

sort():数组排序,默认将所有元素转换成字符串,再按字符串 Unicode 码点排序,返回值是新数组;如果元素都是数字,按从小到大排序,可以传入一个回调函数作为参数。

reverse():颠倒数组中元素的位置。

splice(start, deleteCount, item):start 未开始的索引,deleteCount 表示要移除的数组元素的个数,item 为要添加进数组的元素。

展开数组的方法(数组扁平化)

最简单循环加递归:循环中判断,如果子元素是数组则递归,不是则 push 到新数组。

arr.toString().split(',')

arr.join(',').split(',')

利用 reduce + concat 递归:

arr.reduce(function(init, item) {  
return init.concat(item是数组循环 不是返回}, [])

some+扩展运算符 ...arr

some+Array.from(arr)

some+[].slice.call(arr)

jQuery 是函数吗、操作数组对象、常用方法

jQuery 源码封装在一个匿名函数的自执行环境中,有助于防止变量的全局污染。然后通过传入 window 对象参数,可以使 window 对象作为局部变量使用,同样的传入 undefined 参数,可以缩短查找 undefined 时的作用域链。

(function(window, undefined) {  
window.jQuery = window.$ = jQuery
})(window)

一些简单的 CRUD 操作:

append():父元素将子元素添加到末尾。

prepend():父元素将子元素添加到开头。

after():添加元素到元素后面。

before():添加元素到元素前面。

remove():移除元素。

箭头函数实现原理 为什么没有 this 指向

箭头函数中没有 this 的机制,不会改变 this 的指向;它的 this 是继承而来的,默认指向宿主对象,而不是执行时的对象。

箭头函数和普通函数相比:

  • 不绑定 arguments 对象,也就是说在箭头函数内访问 arguments 对象会报错
  • 不能用作构造器,也就是说不能通过关键字 new 来创建实例
  • 默认不会创建自己原型属性
  • 不能用作 Generator() 函数,不能使用 yield 关键字

提到 arguments

arguments 是具有数组某些特性的「类数组」(伪数组)

每个函数都有一个 Arguments 对象实例 arguments,它引用着函数的实参,可以用数组下标的方式 '[]' 引用 arguments 的元素。

使用场景:有时候使用闭包来实现一次性函数,但是并不确定传参个数,可以在内部使用 apply(this, arguments) 的方式来取实参。

getter setter 提到了 Proxy

getter 函数:获取 object 对象的属性值

setter 函数:对 object 对象的属性进行赋值

通常有两种手段可以对 object 对象存、取值:1. 在对象初始化时,2. 在对象初始化后

// 对象初始化时  
var o = {
key: 0
get getkey () {
return this.key
}
set setkey (value) {
this.key = value
}
}

这里提到了 ES6 的 Proxy 对象,用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)

const person = {  
name: 'sgh',
age: 21
}

构建一个代理对象,第一个参数是需要代理的目标对象:

const personProxy = new Proxy(person, {  
// 监视属性读取
get (target, property) {
// 代理的目标对象外部访问的属性名
return target[property]
}
// 监视属性设置
set (target, property, value) {
// 代理的目标对象外部访问的属性名 写入的属性名
return target[property] = value
}
})

proxy 和 defineProperty 的区别

  • Proxy 更为强大。Object.defineProperty() 只能监视属性的读写,Proxy 能监视到更多对象操作,如 deleteProperty、has 等等。
  • Proxy 更好的支持数组对象的监视。以往想通过 Object.defineProperty() 去监视数组操作,最常见的一种方式是通过重写数组的操作方法(Vue.js 2.x 使用的方法)大体的思路就是通过自定义的方法去劫持对应这个方法调用的过程。但 Proxy 内部会自动根据 push 等操作去推算出它应该所处的下标。
  • Proxy 是以非侵入的方式监管了对象的读写。也就是说已经定义好的对象,不需要对对象本身做任何操作就可以监视到内部成员的读写,而 Object.defineProperty() 就要求我们必须通过特定方式单独定义对象中需要被监视的属性。
  • 提到 ES6,var let const 区别

    const 操作对象 怎么添加对象

    JS 编译提到了 webpack typescript

    Babel 编译平台了解吗 你用的什么 -> presets

    Loader 实现原理

    Webpack 打包流程

    Webpack 构建 开发性能优化

    Vue computed watch 区别

    Vue 组件实现:两个框 对象选中到移动到另一个框 逻辑 有哪些需要注意的

    还有什么要问我的吗

    上一篇:2021年3月-杭州-阿里本地生活基础面试题
    下一篇:表格对比 slice(),splice(),split(),substring(),substr()

    发表评论

    最新留言

    网站不错 人气很旺了 加油
    [***.192.178.218]2025年04月26日 15时12分08秒