关于前端的碎碎念5-web前端常见面试问题总结(3)
1.new操作符过程的理解?
考察对new关键的深刻认识,是否对前端知识有专研,如果没有专研的人,肯定说创建了一个对象,恭喜你面试官知道你是小菜鸟来的,这次面试基本上没有太大的希望了。一定要对new过程的4个步骤非常清楚,这样才能深深地抓住面试官的心!
先看代码
var myFn=function(){ }; var func=new myFn ();
new共经过了4个阶段
1、创建一个空对象
var obj=new Object();
2、设置原型链
obj.__proto__= myFn.prototype;
3、让myFn中的this指向obj,并执行myFn的函数体。
var result =myFn.call(obj);
4、判断Func的返回值类型:
如果是值类型,返回obj。如果是引用类型,就返回这个引用类型的对象。
if (typeof(result) == "object"){ func=result; } else{ func=obj;; }
2.call() 和 apply() 有什么区别?
属于比较一般性的问题,稍有接触基本都可以掌握,先说清楚他们的相同点,方法的作用的,关键在于把它们的差异讲清楚。
相同点:两个方法产生的作用是完全一样的,都用来改变当前函数调用的对象。
不同点:调用的参数不同,比较精辟的总结:
foo.call(this,arg1,arg2,arg3) == foo.apply(this, arguments)==this.foo(arg1, arg2, arg3)
具体的使用
1.call的使用
语法
call([thisObj[,arg1[, arg2[, [,.argN]]]]])
参数
thisObj 可选项。将被用作当前对象的对象。
arg1,arg2, , argN 可选项。将被传递方法参数序列。
说明
call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。
<!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>Document</title> <script> function Obj() { this.value="对象!"; } var value="global 变量"; function myFn(a,b){ alert(this.value); } window.myFn(); //global 变量 myFn.call(window,1,2); //global 变量 myFn.call(document.getElementById('myText')); //global 变量 myFn.call(new Obj()); //对象! </script> </head> <body> <div id="myText"> </div> </body> </html>
2.apply()
apply与call的功能几乎一样,第一个参数意义都一样,只是第二个参数有点不同apply传入的是一个参数数组,也就是将多个参数组合成为一个数组传入,call从第二个参数开始,依次传值给调用函数的参数
3.代码比较
<!doctype html> <html> <head> <meta charset="UTF-8"> <meta name="Generator" content="EditPlus®"> <meta name="Author" content=""> <meta name="Keywords" content=""> <meta name="Description" content=""> <title>Document</title> <script> function print(a, b, c, d){ alert(a + b + c + d); } function example(a, b , c , d) { //用call方式借用print,参数显式打散传递 print.call(this, a, b, c, d); //用apply方式借用print, 参数作为一个数组传递, //这里直接用JavaScript方法内本身有的arguments数组 print.apply(this, arguments); //或者封装成数组 print.apply(this, [a, b, c, d]); } //下面将显示”华为前端” example("华" , "为" , "前", "端"); </script> </head> <body> <div id="myText"> </div> </body> </html>
3.谈谈模块化开发?
主要看你是否有做过比较复杂、庞大的项目,是否具备一定的编程思想。随着前端技术的发展,前端编写的代码量也越来越大,就需要对代码有很好的管理。目前比较好的开发语言就是OOP(面向对象编程)编程语言,例如Java语言、C#语言。从JavaScript新的版本来看,要求JavaScript具有封装、继承、多态这样的优点需求越来越明显。考察编程思想。
什么是模块化
所谓的模块化开发就是封装细节,提供使用接口,彼此之间互不影响,每个模块都是实现某一特定的功能。模块化开发的基础就是函数
使用函数封装
function myFn1(){ //... } function myFn2(){ //... }
上面的函数myFn1 ()和myFn2 (),组成一个模块。使用的时候,直接调用就行了。这种做法的缺点很明显:"污染"了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间看不出直接关系。
使用对象封装 ---为了解决上面的缺点,可以把模块写成一个对象,所有的模块成员都放到这个对象里面。
var obj = { age : 0, myFn1 : function (){ //... }, myFn2 : function (){ //... } };
上面的函数myFn1 ()和myFn2 (),都封装在obj对象里。使用的时候,就是调用这个对象的属性。
obj.myFn1();
这样做也是有问题的,变量可以被外面随意改变而导致不安全。比如,年龄被修成负数。
obj.age = -10;
如何保证对象的属性不被访问了?
立即执行函数写法
使用"立即执行函数"(Immediately-Invoked FunctionExpression,IIFE),可以达到不暴露私有成员的目的。这个也是闭包处理的一种方式。
var obj= (function(){ var _age= 0; var myFn1= function(){ //... }; var myFn2= function(){ //... }; return { m1 : myFn1, m2 : myFn2 }; })();
使用上面的写法,外部代码无法读取内部的age变量。
console.info(obj.age);//undefined
<script> var obj= (function(){ var _age= 0; var myFn1= function(a,b){ return a+b; }; var myFn2= function(a,b){ return a-b }; return { m1 : myFn1(4,5), m2 : myFn2(6,_age) }; })(); console.log(obj.m1);//9 console.log(obj.m2)//6 console.log(obj.age);//undefined </script>
放大模式
如果一个模块很大,必须分成几个部分,或者一个模块需要继承另一个模块,这时就有必要采用"放大模式"(augmentation)。在原有的基础上扩展更多的方法。
var obj =(function (mod){ mod.myFn3= function () { //... }; return mod;//方便方法连续调用 })(obj);
上面的代码为obj模块添加了一个新方法myFn3 (),然后返回新的obj模块,方便方法连续调用。如何防止obj为null或underfined的情况了?
宽放大模式(Loose augmentation)
在浏览器环境中,模块的各个部分通常都是从网上获取的,有时无法知道哪个部分会先加载。如果采用上面的写法,第一个执行的部分有可能加载一个不存在空对象,这时就要采用"宽放大模式"。
var obj =( function (mod){ //... return mod; })(window.obj|| {});//确保对象不为空
与"放大模式"相比,"宽放大模式"就是"立即执行函数"的参数可以是空对象,解决了非空问题。
输入全局变量
独立性是模块的重要特点,模块内部最好不与程序的其他部分直接交互。为了在模块内部调用全局变量,必须显式地将其他变量输入模块。
(function(window, undefined ) { …… })(window );
这是jQuery框架的源码,将window对象作为参数传入,这样做除了保证模块的独立性,还使得模块之间的依赖关系变得明显。目前,通行的JavaScript模块规范共有两种:CommonJS和AMD。CommonJS可以跟进华为前端课程3阶段node模块化。
- 点赞
- 收藏
- 关注作者
评论(0)