这是JS面试题的第一篇,记录的同时也会把一些基础的问题记录下来,并针对一些知识点会有专门文章做讲解。不仅仅是面试题,也是JS的用法总结。
在JS面试题系列中,我会把一些关键的知识点,在B站或书上找到资料后,专门整理成一篇文章,而不是只用几道面试题过了就完了。
大家可以收藏此系列文章,我的JS 知识点相关的文章基本上都会记录在此系列里
JS面试系列
1. 判断字符串是否是这样组成的,第一个必须是字母,后面可以是字母、数字、下划线、总长度为5~20
采用正则,
^[a~z]
是匹配小写的26个字母,[A~Z]
是匹配大写的26个字母,{n}
表示匹配几位,\w
表示任意的字母、数字、下划线
注意:正则有大小之分
代码如下:/^[a~zA~Z]{1}\w[4~19]/
关于正则的一些基础和实例我整理在了这篇文章JS正则
2. JavaScript中如何检测一个变量是string类型?
var str = 'hello world'
function isString(str) {
if(typeof str=="string" || str.constructor == String) {
return true;
} else {
return false;
}
}
3.JS中的数据类型
4.JS中window属性和方法
————————2021 9.11——————————
5.JS中Math的用法
Math.ceil()向上取整
Math.floor()向下取整
Math.round()四舍五入
6.JS中Array常用用法
6.1 获取数组里的最大和最小的数字
Math.max.apply(null,[])
Math.min.apply(null,[])
6.2splice和slice
splice(index,howmany,el1,...,elN)
从指定位置删除部分元素并添加新元素,数组改变
slice()
进行数组的截取,数组不变
6.3 unshift和shift、pop
unshift()可以向数组开头添加一个或多个元素,并返回新的长度
shift()把数组中第一个元素删除,并返回第一个元素的值
pop()删除并返回最后一个元素
7. 写一个获取非行间样式的函数
行间样式:行间样式就是写在标签体内的样式:如,<div style="color:red"></div>
,在这里color样式就是行间样式。
非行间样式:非行间样式就是指不是写在标签体内的style属性的样式。如内的定义的样式或引用的外部css文件都是非行间样式。
function getStyle(obj,attr,value) {//获取非行间样式,obj是对象,attr是值
if(!value) {// 如果需要赋值,就直接赋值
if(obj.currentStyle){//针对ie获取非行间样式
return obj.currentStyle(attr)
} else {
obj.getComputedStyle(attr,false)//针对非ie获取非行间样式
}
}else {
obj.style[attr] = value
}
}
8. 创建一个对象【重点】
这里把JS中创建对象的从低级到高级流程过一遍,我看很多教程和书籍在讲对象这一部分时都会谈到以下方法,这里我就做个统一的整合
8.1原始方法
此方法是通过new关键字生成一个对象,然后根据JS是动态语言的特性来添加属性和方法,构造一个对象
问题:如果需要创建多次对象,需要重复代码多次,不适合复用
<script>
// 原始方法
var obj = new Object()
obj.name='123'//添加属性
obj.showName = function () {} //添加方法
obj.showName()// 调用
</script>
8.2 工厂设计模式
下面代码把方法创建提出来,而不是放在创建对象里。
面向对象强调对象的属性私有,但对象的方法是共享的
而如果放在创建函数里面,则在创建对象时,要为每个对象创建各自私有库的方法。
同时,要为每个对象都创建逻辑相同的方法,所以很浪费内存
**问题:**这种方法会造成函数与对象独立,与面向对象中特定方法属于特定类的思想不符3
<script>
function createObj(name,age) {//构造对象时可以传入初始化参数
var obj = new Object()
obj.name = name
obj.age = age
obj.showName = showName
return obj
}
// 这里把方法创建提出来了
function showName() {}
var obj = createObj('af',23)
</script>
8.3构造函数模式
与工厂方式一样,会为每个对象创建独享的函数对象。也可以放在外面
但也有了对象和方法相互独立的问题
<script type="text/javascript">
//定义一个构造函数,用来生成对应的对象
function Person(name, age) {
//当调用new Person时,在执行第一行代码前,先生成一个Person对象,
//并将对象在内存中的索引赋值给this关键字
// 此时可以通过this关键字操作新创建的对象,如下
this.name = name
this.age = age
this.setName = function (name) {
this.name = name
}
}
var p1 = new Person('Tom', 12)
p1.setName('Jack')
console.log(p1.name, p1.age)
console.log(p1 instanceof Person)
</script>
8.4原型方法
主要问题是:里面某个属性性质改变时,所有对象的属性都会改变
<script>
function Person() {}
Person.prototype.name="afa"
Person.prototype.showName = function(){}
</script>
8.5混合构造函数/原型
这样,属性变为私有,方法则为共享了
function Person(name, age) { //在构造函数中只初始化一般函数
this.name = name
this.age = age
}
Person.prototype.setName = function (name) {
this.name = name
}
var p1 = new Person('Tom', 23)
var p2 = new Person('Jack', 24)
console.log(p1, p2)
8.6动态原型方法
这种方法是将方法的添加放到了构造函数中,同时在构造函数Person上添加了一个属性来保证if语句只能成功执行一次。
function Person(name, age) { //在构造函数中只初始化一般函数
this.name = name
this.age = age
this.array = new Array("fa","fase")
// 如果Person对象中的_initialized为undefined,表明还没有为Person的原型添加方法
if (typeof Person._initialized == "undefined"){
Person.prototype.showName=function () {}
Person._initialized = true//设置为true,不必再添加
}
}
9.map, filter, reduce都怎么用
map
对数组每个元素都遍历一次,同时返回一个新的值,返回的数据长度与原数组一致
// map() 方法的使用
let nums =[10,20,30,40,50]
let newnums = nums.map(function(n){
return n * 3
})
console.log(newnums); // 30,60,90,120,150
filter
此函数主要是过滤作用,即筛选出符合一定条件的元素并组成新数组。
let NewArr = OriArr,filter ( n => n < 100 ) //筛选出数组元素小于100的元素
reduce【重点】
语法
arr.reduce(callback,[initialValue])
reduce为数组中的每一个元素依次执行回调函数,不包括数组中被删除或从未被赋值的元素,接受4个参数,如下
callback (执行数组中每个值的函数,包含四个参数)
1、previousValue (上一次调用回调返回的值,或者是提供的初始值(initialValue))
2、currentValue (数组中当前被处理的元素)
3、index (当前元素在数组中的索引)
4、array (调用 reduce 的数组)
initialValue (作为第一次调用 callback 的第一个参数。)
initialValue解释
如果没有提供初始值,reduce会从索引为1的地方开始
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
})
console.log(arr, sum);
var arr = [1, 2, 3, 4];
var sum = arr.reduce(function(prev, cur, index, arr) {
console.log(prev, cur, index);
return prev + cur;
},0) //注意这里设置了初始值
console.log(arr, sum);
用法
(1)计算数组中每个元素出现的次数
let names = ['Alice', 'Bob', 'Tiff', 'Bruce', 'Alice'];
let nameNum = names.reduce((pre,cur)=>{
if(cur in pre){
pre[cur]++
}else{
pre[cur] = 1
}
return pre
},{})
console.log(nameNum); //{Alice: 2, Bob: 1, Tiff: 1, Bruce: 1}
(2)数组去重
let arr = [1,2,3,4,4,1]
let newArr = arr.reduce((pre,cur)=>{
if(!pre.includes(cur)){
return pre.concat(cur)
}else{
return pre
}
},[])
console.log(newArr);// [1, 2, 3, 4]
(3)将二维数组转化为一维
let arr = [[0, 1], [2, 3], [4, 5]]
let newArr = arr.reduce((pre,cur)=>{
return pre.concat(cur)
},[])
console.log(newArr); // [0, 1, 2, 3, 4, 5]
10. symbol【es6新类型】
关于symbol的介绍,这篇博客已经很详细
11.javascript中的继承是如何工作的
-
- 在子构造函数中执行父构造函数,并用call/apply改变this
-
- 克隆父构造函数原型上的方法
12.javascript中的本地对象、内置对象和数组对象
- ECMA-262 把本地对象定义为“独立于宿主环境的ECMAScript实现提供的对象”。包括以下内容:Object,Function, Array, String, Boolean, Number, Date, RegExp, Error, EvalError, ReferenceError, SyntaxError, TypeError, URIError。因此,本地对象就是ECMA-262定义的类
- 内置对象,实际上不存在,但类似于isNaN(),parseInt(),parseFloat()方法等,都是Global对象的方法。
- 数组对象。由ECMAScript实现的宿主环境提供的对象,可以理解为浏览器提供的对象。所有的BOM和DOM都是数组对象。
13. 编写一个类,类中定义如下属性和方法
共有静态属性和共有静态方法、私有属性和私有方法、特权属性和特权方法、共有静态属性和共有静态方法。
function User(){
// 共有属性
// 特权属性
this.name = 'wjyGrit';
// 特权方法
// 公有方法
this.sayName = function () {
alert(this.name)
alert(this.school)
alert(age) // 变量声明会自动提前
alert(this.sex)
};
//私有属性
var age = 22
//私有方法
function sayAge() {
alert(age)
}
sayAge()
}
// 共有属性:共享内容
// 共有静态属性
User.prototype.school = 'hubt'
// 共有方法:可访问公有属性
// 共有静态方法
User.prototype.saySchool=function () {
alert(this.school)
alert(this.name)
alert(this.sex)
alert(age)
}
var obj = new User()
// 静态属性: 就是动态添加的实例属性
obj.sex = 'man'
obj.saySex = function () {
alert(this.sex)
alert(this.name)
alert(this.school)
alert(age)
}