이 글은 JavaScript에 대한 일반적인 면접 질문과 답변을 요약한 것입니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다.
1. 이것이 JavaScript에서 어떻게 작동하는지 설명해주세요.
우선, 이는 항상 함수가 생성된 개체가 아니라 함수가 실행 중인 개체를 가리킵니다. 익명 함수 또는 어떤 개체에도 없는 함수는 window 를 가리킵니다.
1. 메소드 호출 모드
함수가 객체의 속성으로 저장되면 해당 함수는 객체의 메소드가 됩니다. 함수에서 this의 값은 객체입니다.
var foo = { name: 'fooname', getName: function (){ return this.name } } foo.getName(); // this => foo
2. 함수 호출 모드
함수가 객체의 속성이 아닌 경우. 함수에 있는 this의 값은 전역 개체입니다
참고: 메서드의 내부 함수에 있는 this의 값은 외부 함수의 this가 아니라 전역 개체이기도 합니다
function foo(){ this.name = 'fooname'; } foo(); // this => window
3. 생성자 호출 모드
즉, new 로 호출된 함수는 새로 생성된 객체에 바인딩됩니다.
function Foo(){ this.name = 'fooname'; } var foo = new Foo(); // this => foo
4. 적용 또는 호출 호출 모드를 사용하세요
이 모드에서 호출할 때 함수의 this는 적용 또는 호출 메서드가 호출될 때 허용되는 첫 번째 매개변수에 바인딩됩니다.
function getName(name){ this.name = name; } var foo = {}; getName.call(foo, name); // this =>foo
this의 값을 변경하는 주요 메소드(현재 생각 중인 메소드는 댓글 추가 환영):
apply 또는 call 메소드가 호출될 때 강제로 수정하여 this가 첫 번째 매개변수를 가리키도록 합니다.
Function.bind 메서드를 사용하여 새 함수를 만듭니다. 이는 새 함수에서 제공된 첫 번째 매개변수를 가리킵니다.
2. 프로토타입 상속의 원리를 설명해 주세요.
JavaScript에는 "하위 클래스"와 "상위 클래스" 개념이 없으며 "클래스"와 "인스턴스" 간의 구분도 없습니다. 상속을 달성하기 위해 전적으로 "프로토타입 체인" 모델에 의존합니다.
각 함수 Sub에는 프로토타입 객체를 가리키는 속성이 있습니다. 또한 프로토타입 객체에는 함수를 가리키는 속성 생성자가 있습니다. Sub는 특정 속성을 호출할 때 인스턴스를 생성할 수 있습니다. 이 인스턴스의 메소드, 인스턴스는 먼저 이 메소드나 속성이 있는지 확인합니다. 그렇지 않은 경우 인스턴스 생성자 Sub의 프로토타입 프로토타입, 즉 프로토타입 객체 Sub.prototype이 할당된 경우 검색합니다. 다른 유형의 인스턴스 superInstance는 superInstance에서 검색됩니다. 이 superInstance도 특정 프로토타입 객체를 가리키는 프로토타입 속성을 가지며 한 수준 위로 올라가서 마지막으로 Object.prototype에 도달하여 프로토타입 상속을 형성합니다.
이 원칙을 사용하여 상속 함수를 직접 구현하세요.
function inherits(subType, superType){ var _prototype = Object.create(superType.prototype); _prototype.constructor = subType; subType.prototype = _prototype; }
3. 다음 코드가 IIFE(즉시 호출되는 함수 표현식)가 아닌 이유를 설명하세요. function foo(){ }(); IIFE?
(function fn(){..})()
가 되어 함수를 괄호로 묶어 표현식이 되고, 뒤에 ()를 붙여 함수를 즉시 실행하게 됩니다.
IIFE의 일부 기능:
이름 충돌을 방지하기 위해 범위를 만들고 내부에 많은 수의 임시 변수 코드를 저장합니다.
일부 라이브러리는 범위 오염을 방지하기 위해 이 형식으로 래핑됩니다.
한 번만 실행되는 일부 코드를 실행하세요.
4. (function fn(){..})(), 함수는 대괄호 안에 포함되어 표현식이 되고, 뒤에 ()가 오면 함수가 즉시 실행됩니다.
IIFE의 일부 기능:
이름 충돌을 방지하기 위해 범위를 만들고 내부에 많은 수의 임시 변수 코드를 저장합니다.
일부 라이브러리는 범위 오염을 방지하기 위해 이 형식으로 래핑됩니다.
한 번만 실행되는 일부 코드를 실행하세요.
함수가 호출되면 실행 환경과 범위 체인이 생성된 다음 초기화되어 인수 및 기타 명명된 매개 변수를 기반으로 활성 개체를 형성합니다. 외부 함수 호출이 끝나면 실행 환경과 범위 체인은 소멸되지만 활성 객체는 클로저에 저장되며 클로저 함수 호출이 끝나면 최종적으로 소멸됩니다. 간단히 말해서 클로저는 다른 함수의 내부 변수를 읽을 수 있는 함수입니다. JavaScript에서 클로저는 다른 함수 범위에 있는 변수에 액세스할 수 있는 함수입니다.
사용방법: A함수 내부의 B함수를 A함수의 반환값으로 반환합니다.
이유:
1. 익명 자체 실행 기능
일부 시나리오에서는 내부 변수를 유지할 필요가 없는 init()와 같은 함수가 한 번만 실행되어야 합니다. 클로저를 사용할 수 있습니다. 익명 함수를 만들어서 바로 실행했습니다. 내부 변수는 외부에서 참조할 수 없기 때문에 전역 개체를 오염시키지 않고 함수가 실행된 후 리소스가 즉시 해제됩니다.
2. 캡슐화
캡슐화를 위한 객체 지향 코드 스타일을 시뮬레이션하여 개인 속성이 존재할 수 있도록 합니다.
5. .call과 .apply의 차이점은 무엇인가요?
.call과 .apply는 둘 다 함수 본문에서 이 객체의 값을 변경하는 데 사용된다는 공통점이 있습니다.
두 번째 매개변수가 다르다는 점이 다릅니다. Apply()의 두 번째 매개변수는 배열과 유사한 객체 인수이며, 매개변수는 모두 배열 형식으로 전달되고, call()은 일련의 매개변수를 전달합니다. 예를 들어
Math.max.call(null, 1, 2, 3, 4); //4 Math.max.apply(null, [1, 2, 3, 4]); //4
6. Function.prototype.bind를 설명해 주세요.
Function.prototype.bind方法会创建一个新函数,当这个新函数被调用时,它的this值是传递给bind()的第一个参数, 它的参数是bind()的其他参数和其原本的参数.
七、请指出 JavaScript 宿主对象 (host objects) 和原生对象 (native objects) 的区别?
宿主对象是指DOM和BOM。
原生对象是Object、Function、Array、String、Boolean、Number、Date、RegExp、Error、Math等对象。
八、请指出以下代码的区别:function Person(){}、var person = Person()、var person = new Person()?
function Person(){}
声明一个函数Person()。
var person = Person()
将函数Person()的结果返回给变量person,如果没有返回值则person为undefined。
var person = new Person()
new一个Person的实例对象。
九、请尽可能详尽的解释 Ajax 的工作原理。以及使用 Ajax 都有哪些优劣?
Ajax是无需刷新页面就能从服务器取得数据的一种方法。
Ajax通过XmlHttpRequest对象来向服务器发异步请求,从服务器获得数据,然后用javascript来操作DOM更新页面。
过程
创建XMLHttpRequest对象。
设置响应HTTP请求的回调函数。
创建一个HTTP请求,指定相应的请求方法、url等。
发送HTTP请求。
获取服务器端返回的数据。
使用JavaScript操作DOM更新页面。
缺点
对搜索引擎不友好
要实现Ajax下的前后退功能成本较大
跨域问题限制
十、请解释变量声明提升 (hoisting)。
变量的声明前置就是把变量的声明提升到当前作用域的最前面。
函数的声明前置就是把整个函数提升到当前作用域的最前面(位于前置的变量声明后面)。
//变量的声明前置 console.log(num);//undefined var num = 1; 等价于 //变量的声明前置 var num; console.log(num);//undefined num = 1;
十一、请描述事件冒泡机制 (event bubbling)。
事件冒泡(event bubbling),事件最开始时由触发的那个元素身上发生,然后沿着DOM树向上传播,直到document对象。如果想阻止事件起泡,可以使用e.stopPropagation()。
十二、什么是 “use strict”; ? 使用它的好处和坏处分别是什么?
优点
消除Javascript语法的一些不严谨之处,减少一些怪异行为;
消除代码运行的一些不安全之处,保证代码运行的安全;
提高编译器效率,增加运行速度;
为未来新版本的Javascript做好铺垫。
缺点
严格模式改变了语义。依赖这些改变可能会导致没有实现严格模式的浏览器中出现问题或者错误。
十三、请解释 JavaScript 的同源策略 (same-origin policy)。
同源策略限制了一个源(origin)中加载文本或脚本与来自其它源(origin)中资源的交互方式。同源指的是协议、域名、端口相同,同源策略是一种安全协议。
十四、请解释 JSONP 的工作原理,以及它为什么不是真正的 Ajax。
JSONP(JSON with Padding)是一种非官方跨域数据交互协议,它允许在服务器端集成< script >标签返回至客户端,通过javascript回调的形式实现跨域访问。
因为同源策略的原因,我们不能使用XMLHttpRequest与外部服务器进行通信,但是< script >可以访问外部资源,所以通过JSON与< script >相结合的办法,可以绕过同源策略从外部服务器直接取得可执行的JavaScript函数。
原理
客户端定义一个函数,比如jsonpCallback,然后创建< script >,src为url + ?jsonp=jsonpCallback这样的形式,之后服务器会生成一个和传递过来jsonpCallback一样名字的参数,并把需要传递的数据当做参数传入,比如jsonpCallback(json),然后返回给客户端,此时客户端就执行了这个服务器端返回的jsonpCallback(json)回调。
通俗的说,就是客户端定义一个函数然后请求,服务器端返回的javascript内容就是调用这个函数,需要的数据都当做参数传入这个函数了。
优点 - 兼容性好,简单易用,支持浏览器与服务器双向通信
缺点 - 只支持GET请求;存在脚本注入以及跨站请求伪造等安全问题
补充一点,JSONP不使用XMLHttpRequest对象加载资源,不属于真正意义上的AJAX。
十五、== 和 === 有什么不同?
通俗的说就是===比==要更为严格,===比较过程中没有任何的类型转换。
十六、什么是三元表达式 (Ternary expression)?“三元 (Ternary)” 表示什么意思?
如名字表示的三元运算符需要三个操作数。
语法是
条件 ? 结果1 : 结果2;
这里你把条件写在问号(?)的前面后面跟着用冒号(:)分隔的结果1和结果2。满足条件时结果1否则结果2。
十七、你怎么看 AMD vs. CommonJS?
浏览器端异步和服务器端同步的模块化编程规范
十八、请举出一个匿名函数的典型用例?
定义回调函数,立即执行函数,作为返回值的函数,使用方法var foo = function() {}定义的函数。
十九、描述以下变量的区别:null,undefined 或 undeclared?该如何检测它们?
未定义的属性、定义未赋值的为undefined,JavaScript访问不会报错;null是一种特殊的object;NaN是一种特殊的number;undeclared 是未声明也未赋值的变量,JavaScript访问会报错。
二十、在什么时候你会使用 document.write()?
DOM方法,可向文档写入 HTML 表达式或 JavaScript 代码。
二十一、如何实现下列代码:[1,2,3,4,5].duplicator(); // [1,2,3,4,5,1,2,3,4,5]
Array.prototype.duplicator = function(){ var l = this.length,i; for(i=0;i<l;i++){ this.push(this[i]) } }
二十二、解释 function foo() {} 与 var foo = function() {} 用法的区别
函数声明的两种方法:
var foo = function () {}
这种方式是声明了个变量,而这个变量是个方法,变量在js中是可以改变的。
也:将一个匿名函数赋值给了变量。
function foo() {}
这种方式是声明了个方法,foo这个名字无法改变
二十三、请解释可变 (mutable) 和不变 (immutable) 对象的区别。
在 JavaScript 中,对象是引用类型的数据,其优点在于频繁的修改对象时都是在原对象的基础上修改,并不需要重新创建,这样可以有效的利用内存,不会造成内存空间的浪费,对象的这种特性可以称之为 Mutable,中文的字面意思是「可变」。
Immutable 从字面上翻译成中文是「不可变」。每次修改一个 Immutable 对象时都会创建一个新的不可变的对象,在新对象上操作并不会影响到原对象的数据。
二十四、使用 Promises 而非回调 (callbacks) 优缺点是什么?
Promise是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6将其写进了语言标准,统一了用法,原生提供了Promise对象。
所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise是一个对象,从它可以获取异步操作的消息。Promise提供统一的API,各种异步操作都可以用同样的方法进行处理。
有了Promise对象,就可以将异步操作以同步操作的流程表达出来,避免了层层嵌套的回调函数。此外,Promise对象提供统一的接口,使得控制异步操作更加容易。
Promise也有一些缺点。
首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。
其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。
第三,当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
二十五、请解释同步 (synchronous) 和异步 (asynchronous) 函数的区别。
同步调用,在发起一个函数或方法调用时,没有得到结果之前,该调用就不返回,直到返回结果;
异步调用的概念和同步相对,在一个异步调用发起后,被调用者立即返回给调用者,但调用者不能立刻得到结果,被调用者在实际处理这个调用的请求完成后,通过状态、通知或回调等方式来通知调用者请求处理的结果。
简单地说,同步就是发出一个请求后什么事都不做,一直等待请求返回后才会继续做事;异步就是发出请求后继续去做其他事,这个请求处理完成后会通知你,这时候就可以处理这个回应了。
二十六、你使用哪些工具和技术来调试 JavaScript 代码?
1.javascript的debugger语句
需要调试js的时候,我们可以给需要调试的地方通过debugger打断点,代码执行到断点就会暂定,这时候通过单步调试等方式就可以调试js代码
if (waldo) { debugger; }
这时候打开console面板,就可以调试了
2.DOM断点
DOM断点是一个Firebug和chrome DevTools提供的功能,当js需要操作打了断点的DOM时,会自动暂停,类似debugger调试。
使用DOM断点步骤:
选择你要打断点的DOM节点
右键选择Break on..
选择断点类型
另外的调试方法例如alert, console.log,查看元素等就不再赘述了。
二十七、你会使用怎样的语言结构来遍历对象属性 (object properties) 和数组内容?
for in 语句
一般for循环
数组forEach方法
위 내용은 일반적인 JavaScrip 인터뷰 질문 및 답변 요약의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!