JS面试题--其他

(1)new运算符的作用是什么?

  1. 创建一个空对象
  2. 由this变量引用该对象
  3. 该对象继承该函数的原型(更改原型链的指向)
  4. 把属性和方法加入到this引用的对象中

(2)模拟new运算符

function objectFactory(){
  const obj = new Object();
  const Constructor =[].shift.call(arguments);
  obj.__proto__ = Constructor.prototype;
  const ret = Constructor.apply(obj, arguments);
  return typeof ret ==="object"?ret:obj;
}

(3) call和apply的区别和作用?

作用都是在函数执行的时候,动态改变函数的运行环境(执行上下文)

call和apply的第一个参数是改变运行环境的对象

区别:call从第二个参数开始,每一个参数都会依次传递给调用函数;

apply的第二个参数是数组

func.call(obj,var1,var2,var3);
func.apply(obj,[var1,var2,var3]);

(4)JS中callee和caller的作用是什么?

caller返回一个关于函数的引用,该函数调用了当前函数;callee返回正在执行的函数,也就是指定的function对象的正文。

(5)如果一对兔子每月生一对小兔子,一对新兔从第二月期就开始生小兔子,同时假定每对兔子都是一雌一雄,试问一对兔子在第n个月能繁殖多少对兔子(使用callee完成)?

分析:这是一个典型的斐波那契数列

function getRabbitNum(num){
				var result = [];
				function fn(n){
					if(n<=2){
						result[n]=1;
						return 1;
					}else{
						if(result[n]){
							return result[n];
						}else{
							result[n]=arguments.callee(n-1)+arguments.callee(n-2);
							return result[n];
						}
					}
				};
				fn(num);
				return result;
			}
			console.log(getRabbitNum(10));

 (6)call(),apply()及bind的作用及区别

作用:call、apply及bind都是改变函数执行的上下文,改变了this的指向

区别: call及apply改变了函数的this,并且执行了该函数,而bind是改变了函数的this指向,不执行该函数

			// 案例 call
				var  doThu = function(a,b){
					console.log(this);
					console.log(this.name);
					console.log([a,b]);
				}
				//在stu上添加一个属性doThu,再执行这个函数,就将doThu的this指向了stu
				var stu={
					name:'xiaoming',
 					doThu:doThu
 				}
//只不过call为stu添加了doThu方法后,执行了doThu,然后再将doThu这个方法从stu中删除。
var stu={
						name:'xiaoming',
						}
				doThu.call(stu,1,2);//stu对象 xiaoming [1,2]


//使用call方法调用匿名函数
				var animals =[{specis:'Lion',name:'King'},{specis:'Whale',name:'Fail'}];
				for(var i=0;i<animals.length;i++){
					(function(i){
						this.print=function(){
							console.log(`#${i} ${this.specis}:${this.name}`);//#0 Lion:King #1 Whale:Fail
						}
						this.print();
					}).call(animals[i],i);
				}

Note:使用 call 方法调用函数并且不指定第一个参数(argument) 这时候this的值会被绑定为全局对象,在严格模式下,this 的值将会是 undefined;

call 函数的内部实现原理

	// call 函数的内部实现原理
				Function.prototype.call = function(thisArg,args){
					if(typeof this !=='function'){
						// 调用call的若不是函数则报错
						throw new TypeError('error');
					}
					thisArg = thisArg ||Window;
					thisArg.fn = this; // 将调用call函数的对象添加到thisArg的属性中
/* 					slice()方法返回一个新的数组对象,
					这一对象是一个由 begin 和 end 决定的原数组的浅拷贝(包括 begin,不包括end)。
					原始数组不会被改变。 */
					const result = thisArg.fn(...[...arguments].slice(1));
					delete thisArg.fn; //删除该属性
					return result;
				}

 bind的实现原理比call和apply要复杂一些,bind中需要考虑一些复杂的边界条件。
 bind后的函数会返回一个函数,而这个函数也可能被用来实例化: 

Function.prototype.bind = function(thisArg){
					if(typeof this !=='function'){
						throw new TypeError("not a function");
					}
					//存储函数本身
					const _this = this;
					//取出thisArg的其他参数,转为数组
					const args =[...arguments].slice(1);
					const bound = function(){
						//可能返回一个构造函数,我们可以new F(),所以需要判断
						if(this instanceof bound){
							return new _this(...args,...arguments);
						}
						// apply修改this的指向 把两个函数的参数合并 传给thisArg函数
						//并执行thisArg函数,返回执行结果
					return _this.apply(thisArg, args.concat(...arguments));
					}
					return bound;
				}

(7)JS延迟加载的方式有哪些?

包括defer和async、动态创建DOM(创建script,插入DOM中,加载完毕后回调,按需异步载入JavaScript)

(8)哪些操作会造成内存泄露

内存泄露指的是不再拥有或需要任何对象(数据)之后,它们仍然存在内存中。

如果setTimeout()的一个参数为字符串而非函数,会引起内存泄露

闭包、控制台日志、循环(两个对象彼此引用且彼此保留时,就会产生一个循环)等造成内存泄露

(9)模拟Object.create()方法创建对象,使用现有的对象来提供新创建的对象的proto

function create(proto){
  function F(){};
  F.prototype = proto;
  return new F();
}

(10)如何实现异步编程?

  • 通过回调函数的方式

  优点:简单、容易理解和部署

  缺点:不利于代码的阅读和维护,各个部分之间高度耦合,流程混乱,而且每个任务只能指定一个回调函数。

  • 通过事件监听。可以绑定多个事件

  优点:每个事件可以指定多个回调函数,而且可以去耦合,有利于实现模块化

  缺点:整个程序会变成事件驱动型,运行流程会变得很不清晰

  • 采用发布/订阅方式。性质与事件监听相似,但是明显优于后者
  • 通过Promise对象实现。Promise对象是CommonJS工作组提出的一种规范,旨在为异步编程提供统一接口。它的思想是,每一个异步任务返回一个promise对象,该对象有个then方法,允许指定回调函数

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值