
本文共 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 组件实现:两个框 对象选中到移动到另一个框 逻辑 有哪些需要注意的
还有什么要问我的吗
发表评论
最新留言
关于作者
