1、什么是原型继承?提供代码进行讲解
关键是理解Javascript对象使用的两个阶段,以及.prototype和.__proto__在各个阶段的作用。对象的创建依赖.prototype:,对象一旦建立,它的.__proto__指针就指向这个原型。原型只是普通的对象而已,作为新对象的蓝本,并没有什么特别的;只是有时候从代码看不明显而已,因为这个过程很多时候发生在JS内部。原型只是普通的对象而已,作为新对象的蓝本,并没有什么特别的;只是有时候从代码看不明显而已,因为这个过程很多时候发生在JS内部。
var obj = {} // 以Object.prototype为蓝本创建obj
function func() {} // 以Function.prototype为蓝本创建func对象
var b = Object.create(a) // 以a为蓝本创建b
var person = new Person() // 以Person.prototype为蓝本创建person
成员的调用依赖.__proto__:每个对象都有一个指向其原型(创建时)的指针,对象成员的调用按着这个指针逐级往上追溯。
构造函数=function(){};
原型对象={属性甲:1,属性乙:2};
构造函数.prototype=原型对象;
新建对象=new 构造函数();
新建对象.属性甲=0;
这样新建对象就继承了原型对象,并在自身内覆盖了一层私有属性,但并不改变原型对象的任何属性。
此时新建对象本身相当于{属性甲:0}(算上隐藏的不可枚举属性是{属性甲:0,constructor:构造函数}),但是如果访问新建对象.属性乙这个自身不存在的属性,则会上溯到其原型对象的同名属性。原型对象的属性改变会对所有包括之前创建的新建对象统一有效。方便管理且节省空间。
原型对象亦可层层继承(原型对象本身也可以是基于更上层原型的对象构造的)。
而没有继承任何对象的最顶层对象(也即是={}这种最常见的定义形式,等同于=new Object())的constructor就是Object这个原生超级根对象构造器。
2、描述一下Promise的使用场景,'Promise'它所解决的问题以及现在对于异步操作的解决方案
使用场景:ajax请求,回调函数,复杂操作判断。
Promise是ES6为了解决异步编程所诞生的。
异步操作解决方案:Promise、Generator、定时器
async 是 ES7 才有的与异步操作有关的关键字,和 Promise , Generator 有很大关联的。
await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用。
function testAwait(){
console.log("testAwait");
}
async function helloAsync(){
await testAwait();
console.log("helloAsync");
}
helloAsync();
// testAwait
// helloAsync
3、通过reduce函数来实现简单的数组求和,示例数组[3,4,8,0,9];并且简要描述reduce一般使用场景
法一推荐:
let result=[3,4,8,0,9].reduce((total,value)=>{ //这两个参数是默认参数不用设置的
return total+value
});
法二:
let reduce=(arr)=>{ //第一种常规遍历。
let num=0;
for(let [index,value] of arr.entries()){
num+=value;
}
return num;
}
法三:
let reduce=(arr)=>eval(arr.join("+"));
4、如何实现一个img在div中上下居中
法一:
将display设置bai成table-cell,然后水平居中设du置text-align为center,垂直居中设置vertical-align为middle。
法二:
通过position定位来实现。bai将div设置成相对定位relative,将img设置成绝对定位absolute,left:50%,top:50%,此时图片的左上角位于div的中心,要是图片的中心位于div的中心,就需要将图片向上移动图片高度的一半,并向左移动图片宽度的一半。
5、请从"2017-05-15T09:10:23 Europe/Paris"提取结果['2017','05','15','09','10','23']
// 正则相关的,看他们要的内容就可以知道,要把所有的数字都提取出来,可以写一个只获取数字的正则表达式。
let str = '2017-05-15T09:10:23 Europe/Paris';
let arr = str.match( /\d{1,}/g);
6、描述js中apply和call的用途和区别;最好可以从代码层面来展开
call()和apply()第一个参数将用作函数内 this 的值,用于改变函数的this指向。call和apply的区别在于call()方法接受逗号分隔的参数作为后面的参数,apply()接受一个参数数组作为后面的参数。
// 在这段代码中,参数 1、2、3 被放在数组中一起传入func 函数,它们分别对应func 参数列
表中的a、b、c。
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.apply( null, [ 1, 2, 3 ] );
// call 传入的参数数量不固定,跟apply 相同的是,第一个参数也是代表函数体内的this 指向,
从第二个参数开始往后,每个参数被依次传入函数:
var func = function( a, b, c ){
alert ( [ a, b, c ] ); // 输出 [ 1, 2, 3 ]
};
func.call( null, 1, 2, 3 );
当调用一个函数时,JavaScript 的解释器并不会计较形参和实参在数量、类型以及顺序上的区别,JavaScript 的参数在内部就是用一个数组来表示的。从这个意义上说,apply 比call 的使用率更高,我们不必关心具体有多少参数被传入函数,只要用apply 一股脑地推过去就可以了。call 是包装在apply 上面的一颗语法糖,如果我们明确地知道函数接受多少个参数,而且想一目了然地表达形参和实参的对应关系,那么也可以用call 来传送参数。
call和apply的用途:改变this 指向
7.css中常见的transition解决方案,简要描述一下与keyframe区别
1、transition 需要去触发比如:点击事件、鼠标移入事件;而 animation 可以配合 @keyframe 可以不触发事件就触发这个动画
2、transition 触发一次播放一次;而 animation 则是可以设置很多的属性,比如循环次数,动画结束的状态等等;
3、transition关注的是样式属性的变化,属性值和时间的关系是一个三次贝塞尔曲线;而animation作用于元素本身而不是样式属性,可以使用关键帧的概念,可以实现更自由的动画效果;
4、在性能方面:浏览器有一个主线程和排版线程;主线程一般是对 js 运行的、页面布局、生成位图等等,然后把生成好的位图传递给排版线程,而排版线程会通过 GPU 将位图绘制到页面上,也会向主线程请求位图等等;我们在用使用 aniamtion 的时候这样就可以改变很多属性,像我们改变了 width、height、postion 等等这些改变文档流的属性的时候就会引起,页面的回流和重绘,对性能影响就比较大,但是我们用 transition 的时候一般会结合 tansfrom 来进行旋转和缩放等不会生成新的位图,当然也就不会引起页面的重排了。
8、如何判断变量'x'是否是'{}'
console.log(Object.prototype.isPrototypeOf(value) && Object.keys(value).length === 0)
9、请自行提供一个closure(闭包/封闭空间)的使用代码,并且描述一下closure的概念和利好
闭包定义:"JavaScript闭包就是在另一个作用域中保存了一份它从上一级函数或者作用域得到的变量,而这些变量是不会随上一级函数的执行完成而销毁",对于这样的闭包定义,我是很难看懂。我的理解是,闭包就是能够读取其他函数内部变量的函数。由于在Javascript语言中,只有函数内部的子函数才能读取局部变量,因此可以把闭包简单理解成"定义在一个函数内部的函数"。所以,在本质上,闭包就是将函数内部和函数外部连接起来的一座桥梁。
闭包可以用在许多地方。它的最大用处有两个,一个是前面提到的可以读取函数内部的变量,另一个就是让这些变量的值始终保持在内存中。
function f1(){
var n=999;
//nAdd是一个没有使用var声明的全局变量,这个变量现在指向了在f1函数内部声明的一个匿名函数
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();//result就是f2函数
result();//第一次调用result函数 999
nAdd();//nAdd代表的就是在f1函数内部声明的一个匿名函数,nAdd()就是在调用匿名函数
result();//第二次调用result函数 1000
闭包的优点:可以重复使用变量,并且不会造成变量污染
全局变量可以重复使用,但是容易造成变量污染。局部变量仅在局部作用域内有效,不可以重复使用,不会造成变量污染。闭包结合了全局变量和局部变量的优点。
可以用来定义私有属性和私有方法。
闭包的缺点:比普通函数更占用内存,会导致网页性能变差,在IE下容易造成内存泄露。
10、回答下面一段代码将会输出什么结果
(function() {
var greet = 'Hello world';
var toGreet = [].filter.call(greet, function(element, index) {
return index > 5;
})
console.log(toGreet)
}());