JavaScript面试题-小code
String
字节length
- 编写一个方法求一个字符串的字节长度
方法1:
function GetBytes(str){
var len = str.length;
var bytes = len;
for(var i = 0;i < len;i++){
if(str.charCodeAt(i) > 255){
bytes++;
}
}
return bytes;
}
var s ="j你";
console.log(GetBytes(s)); //中文字占2个字节
方法2:
function getLeng(str){
if(!arguments.length || !str){
return null;
}
var len = str.length;
var newlen = 0;
for(var i = 0; i < len; i++){
if(str.charCodeAt(i) > 255){
newlen += 2;
}else{
newlen++;
}
}
return newlen;
}
var s =" ";
console.log(getLeng(s));
substr-slice
- 截取字符串abcdefg的efg
str = "hello world";
var slice = str.slice(3,7) // 第二个参数位置
var substring = str.substring(3,7) // 第二个参数位置,同上slice方法
var substr = str.substr(3,7) // 第二个参数个数
console.log(slice); // "lo w" ,array也有这个方法,array最强大的方法splice,改变原数组
console.log(str); // "hello world" 不改变原字符串
console.log(substring); // "lo w"
console.log(substr); // "lo worl"
字符串出现最多的char
- 判断一个字符串中出现次数最多的字符,统计这个次数
str = "abcaba";
function getMost(str){
var obj = {};
for(var i = 0; i < str.length; i++){
if(!obj[str.charAt(i)]){
obj[str.charAt(i)] = 1;
}else{
obj[str.charAt(i)] ++ ;
}
}
var max = 0; // 字符出现最多的次数
var index = ""; //出现次数最多的是哪个字符
for(var j in obj){
if(obj[j] > max ){
max = obj[j];
index = j;
}
}
var newObj = {
maxvalue: index,
maxnum: max
}
return newObj;
}
console.log(getMost(str).index);
获取随机String
- 获取随机数,要求是长度一致的字符串格式
var random = Math.random();
random = random + '00000000';
random = random.slice(0,10);
console.log(random);
按照格式showTime
- xxxx年xx月xx日xx时xx分xx秒动态显示时间 要求不足10的补0
<div id="demo"></div>
<script type="text/javascript">
function f(str){
return str > 9 ? str : "0" + str;
}
function getTime(){
var time = new Date();
var year = time.getFullYear();
var month = f(time.getMonth()+1);
var day = f(time.getDate());
var hour = f(time.getHours());
var minutes = f(time.getMinutes());
var second = f(time.getSeconds());
var mytime = year+ "-" + month + "-" + day + " " + hour +":"+ minutes + ":" +second;
return mytime;
}
function intext(){
document.getElementById("demo").innerHTML = getTime()
}
setInterval(intext,1000);
</script>
qian-fen-wei
- 如何将浮点数点左边的数每三位添加一个逗号,如 12000000.11转化为 12,000,000.11 ?
法一:正则匹配
function myNum(num) {
var xs = num.toString().split('.')[1]; // 判断是否有小数部分
if (xs) {
return num && num
.toString()
.replace(/(\d)(?=(\d{3})+\.)/g, function($1, $2){
return $2 + ',';
});
}
return num.toString().replace(/(\d{1,3})(?=(\d{3})+$)/g,'$1,');
}
console.log(myNum(num));
法二:借用数组
var num = 12345678.90;
function turnQFW(num) {
var str = parseInt(num).toString();
var zsLength = parseInt(num).toString().length;
// 小数
var xs = num.toString().split(".")[1];
var iNum = str.length % 3; //余数
var prev = '';
var arr = [];
var iNow = 0;
var tmp = '';
if (iNum !=0) {
prev = str.substring(0,iNum); //将余数截取出来
arr.push(prev);
}
// 剩下规则的3个数为一组,str长度为0、3、6、9、3n
str = str.substring(iNum);
for (var i=0;i<str.length;i++) {
iNow++;
tmp +=str[i];
if(iNow ==3 && tmp) {
arr.push(tmp);
tmp = '';
iNow = 0;
}
}
// 把整数部分变成千分位格式
var zsStr = arr.join(',');
if (zsLength <= 3) {
return num;
} else {
// 如果存在小数位
if (xs) {
return zsStr + '.' + xs ;
}
return zsStr;
}
}
console.log(turnQFW(num));
法三:用正则匹配
function comdify(num) {
var re=/\d{1,3}(?=(\d{3})+$)/g;
var n1=num.toString().replace(/^(\d+)((\.\d+)?)$/,function(s,s1,s2){return s1.replace(re,"$&,")+s2;});
return n1;
}
console.log(comdify(num));
Array
isArray
- js如何判断一个对象是不是Array
方法1:
function isArray(obj){
return Object.prototype.toString.call(obj) === "[object Array]"
}
var arr = "12";
console.log(isArray(arr));
ES6新增数组api,方法2:
Array.isArray(arr);
getType判断JS所有的数据类型
手写一个getType函数,获取详细的数据类型。
Object.prototype.toString.call(x);
= ‘[object Array]’
function getType(x){
const originType = Object.prototype.toString.call(x); // '[object Undefined]'
const spaceIndex = originType.indexOf(' ');
const type = originType.slice(spaceIndex + 1,-1);
return type.toLowerCase();
}
console.log(getType(x))
数组unique
- 编写一个方法 去掉一个数组的重复元素
方法1:
var arr = [ 1,2,3,"1"];
function getArrUnique(arr){
var newArr = [ ];
for (var i = 0; i < arr.length; i++){
if(newArr.indexOf(arr[i]) == -1)
newArr.push(arr[i]);
}
return newArr;
}
方法2,不完善:
function getArrUnique2(arr){
var newArr = [];
var obj = {};
for(var i = 0; i < arr.length; i++){
if(!obj[arr[i]]){
obj[arr[i]] = true;
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(getArrUnique2(arr)); //[1,2,3] error result
改进以上方法,方法2:
function getArrUnique3(arr){
var newArr = [];
var obj ={};
for(var i=0;i<arr.length;i++){
if(!obj[ typeof (arr[i]) + arr[i] ]){
obj[ typeof (arr[i]) + arr[i] ] = true;
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(getArrUnique3(arr)); //[1,2,3,"1"]
方法3: 使用 Set
function getArrUnique(arr){
const set = new Set(arr)
return [...set]
}
Random-ordering
- 如何实现数组的随机排序?
方法一:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort1(arr){
for(var i = 0,len = arr.length;i < len; i++ ){
var rand = parseInt(Math.random()*len);
var temp = arr[rand];
arr[rand] = arr[i];
arr[i] = temp;
}
return arr;
}
console.log(randSort1(arr));
方法二:
var arr = [1,2,3,4,5,6,7,8,9,10];
function randSort2(arr){
var mixedArray = [];
while(arr.length > 0){
var randomIndex = parseInt(Math.random()*arr.length);
mixedArray.push(arr[randomIndex]);
arr.splice(randomIndex, 1);
}
return mixedArray;
}
console.log(randSort2(arr));
方法三:
var arr = [1,2,3,4,5,6,7,8,9,10];
arr.sort(function(){
return Math.random() - 0.5;
})
console.log(arr);
Array Flatten 数组一级拍平
- 写一个JS 函数,实现数组扁平化,只减少一级嵌套
- 如输入[1,[2,[3]],4],输出[1,2,[3],4]
【法一:遍历】
思路:
- 定义空数组 arr = [],遍历当前数组
- 如果 item 非数组,则累加到 arr
- 如果 item 是数组,则遍历之后累加到 arr
var arr = [1,'test',[3,['Str'],9],2];
function arrFlatten(arr) {
let res = [];
const len = arr.length;
for(let i = 0;i < len; i++) {
if(Array.isArray(arr[i])) {
for(let j = 0;j < arr[i].length;j++) {
res.push(arr[i][j])
}
} else {
res.push(arr[i])
}
}
return res
}
console.log(arrFlatten(arr));
【法二: 使用 concat】
var arr = [1,'test',[3,['Str'],9],2];
function arrFlatten2(arr) {
let res = [];
const len = arr.length;
for(let i = 0; i < len; i++) {
res = res.concat(arr[i]); // 使用concat不会改变原来的res数组,这里需要重新赋值
}
return res
}
console.log(arrFlatten2(arr));
Array Flatten 数组深度扁平化
写一个JS函数,实现数组扁平化,减少所有嵌套的层级
思路
- 先实现一级扁平化,然后递归调用,直到所有扁平
var arr = [1,'test',[3,['Str'],9],2];
function arrFlatten(arr) {
let res = [];
const len = arr.length;
for(let i = 0;i < len; i++) {
if(Array.isArray(arr[i])) {
let temp = arrFlatten(arr[i]); // 递归
for(let j = 0; j < temp.length; j++) {
res.push(temp[j])
}
// res = res.concat(arrFlatten(arr[i]));
} else {
res.push(arr[i])
}
}
return res
}
console.log(arrFlatten(arr));
Object
create object
- javascript创建对象的几种方式?
1、对象字面量的方式
person = {firstname:"Mark", lastname:"Yun", age:25, eyecolor:"black"};
2、用function来模拟无参的构造函数
function Person(){}
var person = new Person();//定义一个function,如果使用new"实例化",该function可以看作是一个Class
person.name = "Mark";
person.age = "25";
person.work = function(){
alert(person.name + " hello...");
}
person.work();
3、用function来模拟参构造函数来实现(用this关键字定义构造的上下文属性)
function Pet(name, age, hobby){
this.name = name;//this作用域:当前对象
this.age = age;
this.hobby = hobby;
this.eat = function() {
alert("我叫" + this.name + ",我喜欢" + this.hobby + ",是个程序员");
}
}
var maidou = new Pet("麦兜", 25, "coding");//实例化、创建对象
maidou.eat();//调用eat方法
4、用工厂方式来创建(内置对象)
var wcDog =n ew Object();
wcDog.name = "旺财";
wcDog.age = 3;
wcDog.work = function() {
alert("我是" + wcDog.name + ",汪汪汪......");
}
wcDog.work();
5、用原型方式来创建
function Dog(){
}
Dog.prototype.name = "旺财";
Dog.prototype.eat = function(){
alert(this.name + "是个吃货");
}
var wangcai = new Dog();
wangcai.eat();
6、用混合方式来创建
function Car(name,price){
this.name = name;
this.price = price;
}
Car.prototype.sell = function(){
alert("我是" + this.name + ",我现在卖" + this.price + "万元");
}
var camry = new Car("凯美瑞",27);
camry.sell();
clone
- 浅拷贝:有两种方式,一种是把一个对象里面的所有的属性值和方法都复制给另一个对象,另一种是直接把一个对象赋给另一个对象,使得两个都指向同一个对象。
- 深拷贝:把一个对象的属性和方法一个个找出来,在另一个对象中开辟对应的空间,一个个存储到另一个对象中。
- 两者就在于,浅拷贝只是简单的复制,对对象里面的对象属性和数组属性只是复制了地址,并没有创建新的相同对象或者数组。而深拷贝是完完全全的复制一份,空间大小占用一样但是位置不同!!
简单点来说,就是假设B复制了A,当修改A时,看B是否会发生变化,如果B也跟着变了,说明这是浅拷贝,拿人手短,如果B没变,那就是深拷贝,自食其力。
浅拷贝 shallow copy
法一:直接用=赋值
let a = [0, 1, 2, 3, 4],
b = a;
console.log(a === b); // true
a[0] = 5;
console.log(a, b); // 相同 [5, 1, 2, 3, 4]
法二: Object.assign 方法
var obj = {
a: 1,
b: 2
}
var obj1 = Object.assign({},obj);
obj1.a = 3;
console.log(obj.a) // 1
console.log(obj1.a) // 3
法三: for···in只循环第一层
var obj = {
a:1,
arr: [2,3]
};
var shallowObj = shallowCopy(obj);
function shallowCopy(src) {
var dst = {};
for (var prop in src) {
if (src.hasOwnProperty(prop)) {
dst[prop] = src[prop];
}
}
return dst;
}
//当一个对象属性的引用值改变时将导致另一个也改变
shallowObj.arr[1] = 5;
obj.arr[1] // = 5
深拷贝 deep copy
- 深拷贝一个对象
function deepClone(obj) {
// obj 是 null, 或者不是对象和数组,直接返回
if (typeof obj !== 'object' || obj == null) {
return obj
}
// 初始化返回结果
let result
if (obj instanceof Array) {
result = []
} else {
result = {}
}
for (let key in obj) {
// 保证 key 不是原型的属性
if (obj.hasOwnProperty(key)) {
// 递归调用
result[key] = deepClone(obj[key])
}
}
return result
}
const obj1 = {
age: 20,
address: {
city: 'chongqing'
},
arr: [1,2,3]
}
const obj2 = obj1
obj2.address.city = 'beijing'
console.log(obj1.address.city)
- 实现一个函数clone,可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制
法一:递归
function deepClone(obj){
var o;
switch(typeof obj) {
case "undefined":
break;
case "string":
o = obj + "";
break;
case "number":
o = obj - 0;
break;
case "boolean":
o = obj;
break;
case "object":
if(obj === null){
o = null;
}else if(obj instanceof Array){
o = [];
for(var k in obj){
o[k] = deepClone(obj[k]);
}
}else{
o = {};
for(var k in obj){
o[k] = deepClone(obj[k]);
}
}
break;
default :
o = obj;
break;
}
return o;
}
var s = {fd:"df",fde:{we:3}};
console.log(deepClone(s));
法二:JSON.parse(JSON.stringify(obj)) 用JSON实现深拷贝
var test={
a:"ss",
b:"dd",
c:[
{dd:"css",ee:"cdd"},
{mm:"ff",nn:"ee"}
]
};
var test1 = JSON.parse(JSON.stringify(test));//拷贝数组,注意这行的拷贝方法
console.log(test);
console.log(test1);
test1.c[0].dd="change"; //改变test1的c属性对象的d属性
console.log(test); //不影响test
console.log(test1);
使用JSON.parse(),JSON.stringify()实现对对象的深拷贝
isEqual
手写对象深度比较,模拟 lodash 的 isEqual
function isObject(obj) {
return Object.prototype.toString.call(obj) === '[object Object]'
}
function isArray(arr) {
return Object.prototype.toString.call(arr) === '[Object Array]'
}
function isEqual(obj1, obj2) {
// 值类型
if (obj1 === obj2) {
return true
}
// 类型为对象并且元素个数相同
if (isObject(obj1) && isObject(obj2) && Object.keys(obj1).length === Object.keys(obj2).length) {
for (let key in obj1) {
if (obj1.hasOwnProperty(key)) {
// 递归
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
}
// 类型为数组并且数组长度相同
} else if(isArray(obj1) && isArray(obj2) && obj1.length === obj2.length) {
for (let key in obj1) {
// 递归
const res = isEqual(obj1[key], obj2[key])
if (!res) {
return false
}
}
// 其它类型,均返回false
} else {
return false
}
// 走到这里,说明数组或者对象中所有元素都相同,返回true
return true
}
let obj1 = {
a: 100,
b: {x: 100},
c: ['x', 'y']
}
let obj2 = {
a: 10,
b: {x: 100},
c: {'0':'x','1':'y'}
}
console.log(isEqual(obj1, obj2))
继承的使用-inherit
function Animal(name){
this.name = name;
this.colors = ["red","blue","green"];
this.showName = function(){
return this.name;
}
}
第一种继承,原型链
function Animal(name){...}
function Pig(){
}
Pig.prototype = new Animal(); //继承所有属性和方法,引起引用类型的原型属性会被所有实例共享
var pig1 = new Pig();
pig1.colors.push("black");
console.log(pig1.colors); // ["red", "blue", "green", "black"]
var pig2 = new Pig();
console.log(pig2.colors); // ["red", "blue", "green", "black"]
第二种继承,借用构造函数
function Animal(name){...}
function Cat(myname){
Animal.call(this,"Tom"); // call不能继承对象原型上的方法
}
var cat = new Cat();
console.log(cat.name); // Tom
console.log(cat.showName()); //Tom
function Dog(name,colors){
Animal.apply(this,arguments) ; //同上call
//Animal.apply(this,[nam,colors]) ;
}
var dog = new Dog("fuwa"); // uwa
console.log(dog.name);
第三种,组合继承
function Super(name){
this.name = name;
this.colors = ["red","blue","green"];
}
Super.prototype.sayName = function(){
console.log(this.name);
}
function Sub(myname,age){
//继承属性
Super.call(this,myname);
this.age = age;
}
//继承方法
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
Sub.prototype.sayAge = function(){
console.log(this.age);
}
var sub1 = new Sub("peng",23);
sub1.colors.push("black"); // ["red", "blue", "green", "black"]
console.log(sub1.colors);
sub1.sayName();
sub1.sayAge();
var sub2 = new Sub("youyi",50);
console.log(sub2.colors); // ["red", "blue", "green"]
sub2.sayName();
sub2.sayAge();
重写forEach
- 写一个能遍历对象和数组的通用forEach函数
function forEach(obj, fn) {
var key;
if (obj instanceof Array) {
// 准确判断是不是数组
obj.forEach(function(item, index) {
fn(index, item);
});
} else {
// 不是数组就是对象
for (key in obj) {
fn(key, obj[key])
}
}
}
var arr = [1, 2, 3];
forEach(arr, function(index, item) {
console.log(index, item);
});
var obj = {
x: 100,
y: 200
}
forEach(obj, function(key, value) {
console.log(key, value);
});