下面是“20个必会的JavaScript面试题(小结)”的完整攻略:
1. 介绍JavaScript的数据类型
JavaScript有六种基本数据类型,分别是:数字(Number)、字符串(String)、布尔(Boolean)、null、undefined和对象(Object)。其中,对象又可以分为普通对象、函数、数组等多种类型。
2. 什么是闭包?如何使用闭包?
闭包指的是一个函数能够访问并使用它外部的变量,即使这些变量在函数被调用时,已经不存在或者已经被修改。使用闭包可以有效地避免全局变量的污染。
下面是一个示例代码:
function outer() {
var count = 0;
function inner() {
count++;
console.log(count);
}
return inner;
}
var func = outer();
func(); // 1
func(); // 2
在这个示例中,inner函数可以访问outer函数中定义的count变量,即使outer函数已经执行完毕。并且,第二次调用func()时,count的值依然保留在内存中。
3. 如何遍历JS对象?
可以使用for-in循环来遍历JavaScript对象,for-in循环会遍历对象中的所有属性,包括原型链上的属性。可以通过hasOwnProperty()方法来判断某个属性是否为该对象本身的属性。
下面是一个示例代码:
var obj = { a: 1, b: 2, c: 3 };
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(prop + ': ' + obj[prop]);
}
}
4. 如何判断一个变量是否为数组?
可以使用Array.isArray()来判断一个变量是否为数组,该方法会返回一个布尔值。
下面是一个示例代码:
var arr = [1, 2, 3];
console.log(Array.isArray(arr)); // true
5. 什么是IIFE?
IIFE(Immediately Invoked Function Expression)指的是“立即调用的函数表达式”,它会在定义之后立即执行。使用IIFE可以避免全局变量的污染,同时实现模块化开发。
下面是一个示例代码:
(function () {
var name = 'John';
function sayName() {
console.log('My name is ' + name);
}
sayName();
})();
在这个示例中,一个匿名函数被定义并立即执行,其内部定义了一个name变量和一个sayName函数。在函数执行过程中,sayName函数被调用,并输出“My name is John”。
6. 在JavaScript中,null和undefined有什么区别?
null和undefined都表示一个变量没有被赋值,但它们的含义不同。null表示一个空值或者没有值的对象,undefined表示一个未定义的值或者一个变量声明但没有赋值的值。此外,在比较的时候,null == undefined会返回true。
下面是一个示例代码:
var a;
console.log(a == null); // true
console.log(a == undefined); // true
console.log(typeof a); // "undefined"
var b = null;
console.log(b == null); // true
console.log(b == undefined); // true
console.log(typeof b); // "object"
7. 如何把一个字符串转换成数字?
可以使用parseInt()或者parseFloat()来将一个字符串转换成数字。其中,parseInt()用于将字符串转换为整数,parseFloat()用于将字符串转换为浮点数。如果字符串中包含非数字字符,则转换结果为NaN(Not a Number)
下面是一个示例代码:
var str = "123";
var num = parseInt(str);
console.log(num); // 123
var str1 = "123.45";
var num1 = parseFloat(str1);
console.log(num1); // 123.45
var str2 = "abc";
var num2 = parseInt(str2);
console.log(num2); // NaN
8. JavaScript中的this关键字指的是什么?
this关键字指的是当前执行代码的对象。在函数内部,this指的是函数所在的对象,在全局作用域内,this指的是window对象。
下面是一个示例代码:
var obj = {
name: "John",
sayName: function () {
console.log(this.name);
}
};
obj.sayName(); // "John"
function someFunction() {
console.log(this);
}
someFunction(); // window
在这个示例中,sayName函数中的this指的是obj对象,而在someFunction函数中,this指的是window对象。
9. JavaScript中的事件流是什么?
事件流指的是用户触发一个事件后,该事件从最外层的元素(一般是整个文档)开始发生,逐渐向下到达被触发的元素,然后再从被触发的元素一级级向上传递到最外层元素。
事件流分为三种:捕获阶段、目标阶段和冒泡阶段。捕获阶段从最上层的元素到事件的目标元素,目标阶段是事件到达目标元素时发生,而冒泡阶段则是从目标元素到最上层的元素。
10. 如何阻止事件的默认行为?
可以使用事件对象的preventDefault()方法来阻止事件的默认行为。一般在处理表单提交和超链接点击等事件时,可以使用该方法。
下面是一个示例代码:
<a href="https://www.google.com" id="link">Google</a>
<script>
document.getElementById('link').addEventListener('click', function (e) {
e.preventDefault();
});
</script>
在这个示例中,当用户点击链接后,事件会被触发并传递到事件监听器中。在事件监听器内部,使用e.preventDefault()方法阻止了链接的默认跳转行为。
11. 什么是跨域?如何解决跨域问题?
跨域指的是在同一域名下,但是端口号或者域名不同,或者不同协议(http/https),或者不同二级域名的情况。由于浏览器的同源策略,跨域请求会被禁止,但是可以使用JSONP、CORS等方式解决跨域请求的问题。
其中,JSONP是利用script标签的src属性跨域请求的一种方式,而CORS是利用浏览器发送OPTIONS请求和服务器设置相应Header的方式来实现跨域请求的。
12. JavaScript中的原型与原型链是什么?
JavaScript中的每个对象都有一个原型对象,它包含了一些可供该对象调用的属性和方法。在面向对象的继承中,子类可以继承父类的原型,并在该基础上进行扩展。
原型链指的是由对象指向对象的原型,再由原型指向原型的原型,形成的一个链式结构。当一个对象调用一个属性或者方法时,如果该对象本身不存在该属性或者方法,则会沿着原型链向上查找,直到找到该属性或者方法为止。
下面是一个示例代码:
var obj = {};
console.log(obj.__proto__ == Object.prototype); // true
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function () {
console.log('My name is ' + this.name);
};
var john = new Person('John');
john.sayName(); // "My name is John"
在这个示例中,obj对象的原型是Object.prototype对象,john对象的原型是Person.prototype对象。
13. 如何判断一个变量是否为函数?
可以使用typeof运算符来判断一个变量是否为函数,当变量类型为function时,返回值为'function'。
下面是一个示例代码:
function someFunction() {
}
console.log(typeof someFunction); // "function"
14. 如何解决JS中异步编程的问题?
可以使用回调函数、Promise、async/await等方式来解决JavaScript中的异步编程问题。
其中,回调函数是一种传递函数的方式,将异步任务的结果通过回调函数传递给调用者。而Promise是一种ES6中新增的异步编程方式,它可以更好地解决回调函数带来的回调地狱问题。最新的ES7中提供了async/await语法,可以将异步编程的代码看成同步代码来编写。
下面是一个使用Promise的示例代码:
function getData() {
return new Promise(function (resolve, reject) {
$.ajax({
url: '/data',
type: 'GET',
success: function (data) {
resolve(data);
},
error: function (err) {
reject(err);
}
});
});
}
getData().then(function (data) {
console.log(data);
}).catch(function () {
console.log('Error!');
});
在这个示例中,getData函数返回了一个Promise,然后通过调用then和catch来处理成功和失败的情况。
15. 什么是JS中的柯里化?
柯里化是一种将接受多个参数的函数转换为接受单一参数的函数的技术。柯里化函数返回一个新函数,新函数接受之前的某些参数,在执行上等同于原函数接收到这些参数的效果。
下面是一个示例代码:
function add(a, b) {
return a + b;
}
function curry(fn) {
var args = Array.prototype.slice.call(arguments, 1);
return function () {
var innerArgs = Array.prototype.slice.call(arguments);
var finalArgs = args.concat(innerArgs);
return fn.apply(null, finalArgs);
};
}
var addTen = curry(add, 10);
console.log(addTen(5));
console.log(addTen(10));
在这个示例中,curry函数实现了柯里化,将add函数转换成了接受单一参数的函数addTen,执行addTen(5)相当于执行add(10, 5)。
16. JavaScript中的事件委托是什么?
事件委托指的是将事件处理器添加到父元素上,代替添加到每个子元素上,从而避免给大量的元素绑定事件处理器,减少页面的事件处理器数量,提高性能。
下面是一个示例代码:
<ul id="list">
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<script>
document.getElementById('list').addEventListener('click', function (e) {
if (e.target.nodeName === 'LI') {
console.log(e.target.innerHTML);
}
});
</script>
在这个示例中,事件处理器被添加到了ul元素上,在点击子元素时会触发事件处理器,并通过判断子元素的nodeName来进行处理。
17. 如何获取元素的位置和尺寸?
可以使用元素的offsetTop、offsetLeft、offsetWidth和offsetHeight属性来获取元素的位置和尺寸。
其中,offsetTop和offsetLeft属性表示元素左上角相对于父元素左上角的距离,而offsetWidth和offsetHeight属性表示元素的宽度和高度。
下面是一个示例代码:
var element = document.getElementById('myDiv');
console.log(element.offsetTop);
console.log(element.offsetLeft);
console.log(element.offsetWidth);
console.log(element.offsetHeight);
18. JavaScript中的setTimeout和setInterval有什么区别?
setTimeout和setInterval都是JavaScript中的定时器方法,它们可以让函数在一定时间后执行,setTimeout在指定时间后执行一次,而setInterval在指定时间间隔内多次执行。
下面是一个示例代码:
setTimeout(function () {
console.log('Hello');
}, 1000);
var i = 0;
var interval = setInterval(function () {
console.log(i++);
if (i == 5) {
clearInterval(interval);
}
}, 1000);
在这个示例中,setTimeout方法会在1秒后执行一次,而setInterval方法会每1秒输出一个数字,当输出数字达到5时停止执行。
19. 如何创建一个对象?
可以使用对象字面量、构造函数、Object.create等方式来创建一个JavaScript对象。
下面是一个使用对象字面量创建对象的示例代码:
var person = {
name: 'John',
age: 30,
sayName: function () {
console.log(this.name);
}
};
person.sayName();
在这个示例中,使用对象字面量创建了一个person对象,包含了name、age、sayName三个属性。
20. JavaScript中的模块化是什么?
JavaScript模块化指的是将代码划分为独立的模块,每个模块仅暴露所需的接口,而不关心其他模块的实现细节。可以使用CommonJS、AMD、ES6等规范来实现JavaScript模块化。
其中,CommonJS是Node.js采用的模块化规范,允许模块化代码的导入与导出。而AMD(Asynchronous Module Definition)是一种异步模块加载规范,可以在浏览器中实现模块化开发。最新的ES6中新增了import和export语法,可以更加方便地进行模块化开发。
下面是一个使用CommonJS规范的示例代码:
// file_A.js
var b = require('./file_B.js');
console.log(b.name);
// file_B.js
var name = 'John';
module.exports.name = name;
在这个示例中,file_A.js使用了require方法来引入了file_B.js模块,并输出了其中的name属性。file_B.js中通过exports对象暴露了name属性。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:20个必会的JavaScript面试题(小结) - Python技术站