JavaScript第二篇
一些常见的面试题内容,希望也能助你一臂之力🌸🌸🌸🌸🌸
Q1、作用域,原型,this的指向?
1、this是什么?
任何函数本质上都是通过某个对象来调用的,没有指定就是window
所有函数内部都有一个变量this
可以调用函数的当前对象
2、如何确定this的值?
test(); //函数调用,this指向 window
p.test();//对象调用方法,this指向该对象 p
new test();// new 关键字创建的对象,this指向 新创建的对象
p.call(obj); //call和raplay调用函数的this 指向该 obj
//举个例子
function Foo(){
getName = function(){console.log(1)}; //全局的,window
// this.getName = function(){}; //这才是Foo的
return this;
}
Foo.getName = function(){console.log(2)};
Foo.prototype.getName = function(){console.log(3)};
var getName = function(){console.log(4)};
function getName(){console.log(5)};
Foo.getName(); // 打印2,函数身上的方法
getName(); // 打印4,有个误区可能觉得是5,但是【变量优先级 > 普通函数】
Foo().getName(); // 打印1, Foo()函数调用,this指向window,相当于window.getName()
getName(); // 打印1,1覆盖了4
new Foo().getName(); // 打印3,往原型身上找
// 结果 2 4 1 1 3
var o = {
a:10,//误导,这里只是o的一个属性
b:{
// a:20, //这里写了,则this.a=20,否则为undefined
fn:function(){
console.log(this.a); //undefined,先在自身找,然后顺着原型链找
console.log(this); // {fn: ƒ}
}
}
}
o.b.fn();
// 结果:undefined {fn: ƒ}
var length = 10;
function fun(){
return this.length + 1; //先在自身找length,没有则再往上找
}
var obj = {
length:5,
test1:function(){
return fun();
}
}
obj.test2 = fun; //函数体,往对象身上加了一个方法
console.log(obj.test1()); //11
// console.log(obj.test2()); //6
console.log(fun() == obj.test2()); // 11 != 6 false
console.log(obj.test1() == obj.test2());// 11 != 6 false
//结果:11 false false
Q2、js判断变量是不是数组的方法有哪些?
// isArr
arr = [1,2,3]
console.log(Array.isArray(arr))
// instanceof
console.log(arr instanceof Array)
// prototype
console.log(Object.prototype.toString.call(arr)) //[object Array]
// isPrototypeOf
console.log(Array.prototype.isPrototypeOf(arr))
// constructor
console.log(arr.constructor.toString().indexOf('Array') > -1)
// 结果 true true [object Array] true true
Q3、slice和splice有什么区别?
//举个例子
arr1 = [1,2,3,4,5,6]
console.log(arr1.slice(1,3)) //[2,3] (start,end)截取数据
console.log(arr1); //[1,2,3,4,5,6],不改变原数组
arr2 = [1,2,2,3,3,4];
console.log(arr2.splice(1,3,0)); //[2,2,3],(start,count,num),截取数据
console.log(arr2);//[1, 0, 3, 4],改变原数组
Q4、new操作符具体做了什么?
1、创建一个空对象
2、将空对象的原型,指向该构造函数的原型
3、将空对象作为构造函数的上下文(改变this指向)
4、对构造函数有返回值的处理判断
//举个例子
function Foo(){
// console.log(this);//使用new 指向的是Foo,否则就是window
this.name = 'zs'
// return 1111 //基本数据类型,忽略
return {name:'lisi'} //return返回类型,引用类型,则以引用类型为主
}
console.log(new Foo());
// 结果:Foo{},{name:'list'}
console.log(Foo())
// 结果:window,{name:'list'}
function Fun(age,name){
this.age = age;
this.name = name;
}
function create(fn,...args){
// 创建一个空对象
var obj = {};//字面量创建对象 //var obj = Object.create({});声明式
// 将空对象的原型,指向构造函数的原型
Object.setPrototypeOf(obj,fn.prototype);
// 将空对象作为构造函数的上下文
var result = fn.apply(obj,args);
// 对构造函数的返回值做处理判断
return result instanceof Object ? result : obj;
}
console.log(create(Fun,18,'za'));
// 结果:Fun {age: 18, name: 'za'}
Q5、什么是闭包?
1、如何产生闭包?
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包
2、闭包是什么?
(1)嵌套的内部函数
(2)包含引用变量(函数)的对象(存在于嵌套函数的内部函数中)
3、产生条件
函数嵌套
内部函数引用了外部函数的数据(变量|函数)
//举个例子
function fun1(){
var a = 2;
function fun2(){ //执行函数就会产生闭包(即使没有调用内部函数)
console.log(a)
}
}
fun1();
Q6、常见的闭包有哪些?
// 1、将函数作为另一个函数的返回值
function fun1(){
//此时闭包就已经产生了(函数提升,内部函数对象已经创建了)
var a = 1;
function fun2(){
a++;
console.log(a)
}
return fun2;
}
var f = fun1();
f(); //2
f(); //3
// 结果 2 3
f = null; //闭包死亡(包含 闭包的函数对象 成为垃圾对象)
// 2、将函数作为实参传递给另一个函数调用
function showDelay(msg,time){
setTimeout(function(){
alert(msg)
}, time);
}
showDelay('闭包',2000);
//结果:延时2s弹框提示 闭包
Q7、闭包的作用?
1、使用函数内部的变量在函数执行完后,任然存活在内存中(延长了局部变量的生命周期)
2、让函数在外部可以操作(读写)到内部函数的数据(变量|函数)
Q1:函数执行完后,函数内部声明的局部变量是否还能存在?
一般不存在,存在于闭包中的变量才可以存在
Q2:在函数外部能直接访问函数内部的局部变量吗?
不能,但是可以通过闭包让外部函数操作它
Q8、闭包的生命周期
(1)产生:在嵌套内部 执行函数定义 时就产生了(不是在调用)
(2)死亡:在嵌套的内部函数成为垃圾对象时
Q9、闭包的应用有哪些?
定义js模块
具有特定功能的js文件
将所有的数据和功能都封装在一个函数内部(私有的)
只向外暴露一个包含n个方法的对象或函数
模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
Q10、闭包的缺点有哪些?
1、函数执行完后,函数内部的局部变量没有释放,占用内存时间会变长
2、容易造成内存泄漏
解决办法:能不用就不用|及时释放
(1)内存溢出
一种程序运行出现的错误
当程序运行需要的内存超过了剩余的内存时,就抛出了内存溢出的错误
(2)内存泄漏
占用的内存没有及时释放
内存泄漏积累多了就容易导致内存溢出
常见的内存泄露 【一般发生在IE或低版本浏览器】
意外的全局变量(不用var 定义局部变量)
没有及时清理的计时器或回调函数
使用了闭包
休息一下,下一篇下一篇