JS基础知识(覆盖JS基础面试题)

38,913 阅读7分钟

总结一些前端基础的知识,有些知识可能在前端面试的时候会问到,所以做个记录,也有助于其他人查看,如果有什么问题,可以指出,会积极修正。

变量类型和计算

JS中typeof的类型有哪些

    console.log(typeof undefined);  //undefined
    console.log(typeof 123);  //number
    console.log(typeof '123');  //string
    console.log(typeof true); //boolean
    console.log(typeof [1,2,3]);  //object
    console.log(typeof {"id": 11}); //object
    console.log(typeof null); //object
    console.log(typeof console.log);  //function

类型转换

  • 显式类型转换
    • Number 函数
      • 数字:转换后还是数字
      • 字符串:如果可以被解析为数值,则为相应的数值,如果不能,则是 NaN,如果是空字符串那就是0
      • 布尔值:true为1,false为0
      • undefined:NaN
      • null:0
      • object:先执行valueOf,看是否能转换,如果不可以再执行toString,看是否可以转换,如果不可以报错
    • String 函数
      • 数字:转换成对应的字符串
      • 字符串:还是对应的字符串
      • 布尔值:true为'true',false为'false'
      • undefined:undefined
      • null:null
      • object:先执行toString,看是否能转换,如果不可以再执行valueOf,看是否可以转换,如果不可以报错
    • Boolean
      下面这几个是false,其他都是true
      • NaN
      • null
      • undefined
      • 0
      • ""
      • false
  • 隐式类型转换
    • 四则运算
    • 判断语句
  • 奇葩的类型转换面试题

何时使用==,何时使用===

除了obj.a == null以外,都用=====要用的时候一定要是已经定义的
obj.a == null 转换之后其实是 obj.a == null || obj.a == undefined

JS中有哪些内置函数

    Object
    Array
    Boolean
    Number
    String
    Function
    Date
    RegExp
    Error

JS变量按照存储方式有哪些类型

  • 1.值类型
  • 2.引用类型(节省空间,公用内存块)

区别:值类型改变一个不会影响其他的,引用类型改变都改变,因为公用内存块

如何理解JSON

JSON是JS的一个对象,也是一种数据格式,JSON中的两个api如下

  1. 将JSON字符串转换成JSON对象 JSON.parse()
  2. 将JSON对象转换成JSON字符串 JSON.stringify()

使用Object.prototype.toString获取一个对象的类型

var toString = Object.prototype.toString;

toString.call(new Date); // [object Date]
toString.call(new String); // [object String]
toString.call(Math); // [object Math]
toString.call(/s/); // [object RegExp]
toString.call([]); // [object Array]

//Since JavaScript 1.8.5
toString.call(undefined); // [object Undefined]
toString.call(null); // [object Null]

原型和原型链

原型的五条规则

  1. 所有的引用类型都可以自定义添加属性
  2. 所有的引用类型都有自己的隐式原型(proto
  3. 函数都有自己的显式原型(prototype)
  4. 所有的引用类型的隐式原型都指向对应构造函数的显示原型
  5. 使用引用类型的某个自定义属性时,如果没有这个属性,会去该引用类型的__proto__(也就是对应构造函数的prototype)中去找

原型链.png

如何准确判断一个变量是数组类型

arr instanceof Array

instanceof判断一个引用类型是什么引用类型,是通过__proto__(隐式原型一层一层往上找,能否找到对应构造函数的prototype)

写一个原型链继承的例子

function Element(ele) {
  this.ele = document.getElementById(ele);
}

Element.prototype.html = function(val) {
  var ele = this.ele;
  if (val) {
    ele.innerHTML = val;
    return this;
  } else {
    return ele.innerHTML;
  }
};

Element.prototype.on = function(type, fn) {
  var ele = this.ele;
  ele.addEventListener(type, fn);
  return this;
}

var element = new Element('main');

element.html('hello').on('click', function() {
  alert('handleClick');
});

描述new一个对象的过程

  1. 创建一个新对象
  2. this指向这个新对象
  3. 执行代码给this赋值
  4. return this
function Foo(name) {
  this.name = name;
  // return this;  // 本身会执行这一步
}

var f = new Foo('shiyanping');

作用域及闭包

变量提升

以下两种情况会进行提升:

  1. 变量定义
  2. 函数说明

this几种不同的使用场景

  1. 在构造函数中使用(构造函数本身)
  2. 作为对象属性时使用(调用属性的对象)
  3. 作为普通函数时使用(window)
  4. call,apply,bind(执行的第一个参数)
var a = {
  name: 'A',
  fun: function() {
    console.log(this.name);
  }
};

a.fun();  //this === a
a.fun.call({ name: 'B' });  //this === { name: 'B' }
var fun1 = a.fun;
fun1(); //this === window

创建10个a标签,点击每个弹出对应的序号

var i;
for (i = 0; i < 10; i++) {
  (function(i) {
    // 函数作用域
    var a = document.createElement('a');
    a.innerHTML = i + '<br>';
    a.addEventListener('click', function(e) {
      e.preventDefault();
      alert(i);
    });
    document.body.appendChild(a);
  })(i);
}

如何理解作用域

  1. 自由变量
  2. 作用域链,及自由变量的查找,找不到逐级向上找
  3. 闭包的两个场景
    1. 函数作为变量传递
    2. 函数作为返回值

实际开发中闭包的应用

// 判断一个数字是否出现过
function isFirst() {
  var _list = [];
  return function(id) {
    if (_list.indexOf(id) >= 0) {
      return false;
    } else {
      _list.push(id);
      return true;
    }
  };
}

var first = isFirst();
first(10);
first(10);
first(20);

单线程和异步

同步和异步的区别,分别列举一个同步和异步的例子

同步会阻塞代码,但是异步不会 alert是同步 setTimeout是异步

关于setTimeout的笔试题

console.log(1);
setTimeout(function() {
  console.log(2);
}, 0);
console.log(3);
setTimeout(function() {
  console.log(4);
}, 1000);
console.log(5);
// 输出结果:1,3,5,2,4

前端使用异步的场景

  1. 定时任务:setTimeout,setInterval
  2. 网络请求:ajax请求,动态img加载
  3. 事件绑定

需要等待的情况下都需要异步,因为不会像同步一样阻塞

日期和Math

知识点:

日期

console.log(Date.now());  // 获取当前毫秒数
var dt = new Date();  // 获取当前时间
console.log(dt.getTime());  // 当前时间的毫秒数
console.log(dt.getFullYear());  //  年
console.log(dt.getMonth()+1); // 月(0-11)
console.log(dt.getDate());  // 日(0-31)
console.log(dt.getHours()); // 时(0-23)
console.log(dt.getMinutes()); // 分(0-59)
console.log(dt.getSeconds()); // 秒(0-59)

Math

  • Math.random() - 返回 0 ~ 1 之间的随机数
  • Math.abs(x) - 返回数的绝对值
  • Math.ceil(x) - 向上取整
  • Math.floor(x) - 向下取整

常用的数组api

  • forEach(遍历所有元素)
var arr = ['a', 'b', 'c', 'd'];
arr.forEach(function (item, index) {
  console.log(item + ',' + index);
})
  • map(对数组进行重新组装,生成新的数组)
// map,生成新数组,不改变原来数组的格式
var arr = ['a', 'b', 'c', 'd'];
var result = arr.map(function (item, index) {
  return index + '/' + item;
})
console.log(result);
  • sort(对数组进行排序)
// sort, 会改变原来数组
var arr = [1, 23, 3, 4];
var result = arr.sort(function (a, b) {
  // 从小到大排序
  return a - b;

  // 从大到小排序
  // return b - a;
})
console.log(result);
  • filter(过滤符合条件的元素)
var arr = [1, 2, 3, 4];
var result = arr.filter(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);
  • every(判断所有元素是否都符合要求)
var arr = [1, 2, 3, 4];
var result = arr.every(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);   // false
  • some(判断是否有至少一个元素符合条件)
var arr = [1, 2, 3, 4];
var result = arr.some(function (item, index) {
  if (item < 3) {
    return true
  }
})
console.log(result);  // true
  • join(根据条件对数组组合成字符串)
var arr = [1, 2, 3, 4];
var result = arr.join(',');
console.log(result);
  • reverse(将数组反转)
var arr = [1, 2, 3, 4];
var result = arr.reverse();
console.log(result);

常用的对象api

  • for in
  • hasOwnProperty(检查属性是不是对象自有的,排除从原型链找到的属性)
 var obj = {
  x: 10,
  y: 20,
  z: 30
}

for (var key in obj) {
  if (obj.hasOwnProperty(key)) {
    console.log(key + ':' + obj[key]);
  }
}

问题:

获取当前日期

function formatDate(dt) {
  if (!dt) {
    dt = new Date();
  }
  var year = dt.getFullYear();
  var month = dt.getMonth() + 1;
  var date = dt.getDate();

  if (month < 10) {
    month = '0' + month;
  }

  if (date < 10) {
    date = '0' + date;
  }

  return year + '-' + month + '-' + date;
}

var nowDate = new Date();
var formatDate = formatDate(nowDate);
console.log(formatDate);

获取随机数,要求长度一致的字符串格式

function randomStr(len) {
  var random = Math.random();
  random = random + '0000000000'; // 防止自动生成的数字不满足长度报错并且强制转换成字符串
  return random.substr(0, len)
}

console.log(randomStr(20));

写一个能遍历对象和数组的通用forEach函数

function forEach(obj, fn) {
  if (obj instanceof Array) {
    obj.forEach(function (item, index) {
      fn(index, item);
    })
  } else {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        fn(key, obj[key]);
      }
    }
  }
}

var arr = [1, 2, 3, 4];
forEach(arr, function (index, item) {
  console.log(index + ',' + item);
});

var obj = {
  x: 10,
  y: 20
};
forEach(obj, function (index, item) {
  console.log(index + ',' + item);
});

阅读完后两部曲

  1. 喜欢的小伙伴点个赞吧,感觉对身边人有帮助的,麻烦动动手指,分享一下。非常感谢各位花时间阅读完,同时很感谢各位的点赞和分享。
  2. 希望各位关注一下我的公众号吧,新的文章第一时间发到公众号,公众号主要发一些个人随笔、读书笔记、还有一些技术热点和实时热点,并且还有非常吸引人的我个人自费抽奖活动哦~