JS面试题1

  1. 延迟加载JS有哪些方式?

defer: 等html全部解析完成,才会执行js代码,顺次执行js脚本

async:是和html解析同步的,不是顺次执行js脚本(当有很多个js时),是谁先加载完谁先执行。
<script defer type="text/javascript" src='script.js'></script>

javascript 复制代码
<html>
<head>
  <title></title>
  // <script type="text/javascript" src='script.js'></script> 放这里的话,浏览器会先解析并执行js才会加载dom
</head>
<body>
  <div id='box'>1111111</div>
  <script type="text/javascript" src='script.js'></script> //一般放在这里,这样的话就会先解析dom,其次才解析并执行js,这样做的好处就是,即使js出现了错误也不会影响dom的渲染。
</body>
</html>

/* 延迟加载JS */
<html>
<head>
  <title></title>
  // 这样写,加个defer或者async,就可以做到使JS延迟加载
  <script defer type="text/javascript" src='script.js'></script>
</head>
<body>
  <div id='box'>1111111</div>
</body>
</html>
// script.js文件
console.log( document.getElementById('box') )
  1. JS的数据类型有哪些

基本类型:string,number,boolean,undefined,null,symbol
引用数据类型:object

  1. JS数据类型考题
javascript 复制代码
<script>
  alert( true + 1); // 2
  alert( 'name' + true); // nametrue
  alert( undefined +1); // NAN
  alert( typeof null); // obj
</script>

<script>
  alert( typeof(NAN) ); // number (NAN是一个数值类型,但不是一个具体的数字)
  alert( typeof(undefined) ); // undefined
  alert( typeof(null) ); // obj
</script>
  1. null和undefined的区别
  1. 作者在设计js的时候先设计的null(设计js的时候借鉴了java)

  2. null会被隐式转换为0(出现错误的时候不容易被发现)------>因此才设计出了undefined

javascript 复制代码
<script>
  alert ( Number(null) ); // 0
  alert( Number(undefined) ); // NAN
</script>

具体的区别:

null是一个表示"无"的对象(空指针对象),转为数值时为0;

undefined是一个表示"无"的原始值,转为数值时为NAN;

  1. ==和===的区别

==:比较的是值(会通过valueOf进行一个隐式转换)

===:除了比较值,还比较类型

javascript 复制代码
/* 会通过valueOf进行一个隐式转换 */
<script>
  alert( 1 == '1' ); // ture  会发生隐式转换:string-->number
  alert( true == 1 ); // true 会发生隐式转换:boolean-->number
  alert( null == undefined ); // true
  alert( [1,2] == '1,2' ); // true 会发生隐式转换:object-->基本数据类型

  var s = '2';
  if( s == 2 ){
    alert ( typeof s ); //string  注意这里还是string,而不是number
  }
</script>

/* valueOf()方法通常由JavaScript在后台自动调用,并不显式的出现在代码中*/
  1. JS的微任务和宏任务

JS语言的一大特点就是单线程,也就是说,同一时间只能做一件事。
单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务,如果前一个任务耗时很长,后一个任务就不得不一直等着。
代码执行任务的优先级:同步代码>异步代码(微任务>宏任务)

  1. JS作用域
  1. 除了函数外,JS没有块级作用域
javascript 复制代码
/* 因为函数有作用域,所以拿不到a */
<script>
function fun(){
  var a = 10;
}
fun();
console.log(a); // 会报错"a is not defined"
</script>

/* 因为没有作用域,所以可以打印出i */
<script>
for( var i=0; i<10; i++){
}
console.log( i ); //i打印出结果为10
</script>
  1. 作用域是指这个变量或者说这个代码起作用的范围

作用域链:内部可以访问外部的变量,但外部不可以访问内部的

javascript 复制代码
/* 内部是可以访问外部的 */
<script>
function fun(){
  var a = 10;
  function foo(){
    console.log( a ); // a为10
  }
  foo();
}
foo();
</script>
/* 内部有先拿内部的,没有再去外部找 */
<script>
var a = 10;
function fun(){
  var a = 20;
  function foo(){
    var a = 30;
    console.log( a ); // a为30
  }
  foo();
}
foo();

注意声明变量是用var还是没有写(window.)

javascript 复制代码
<script>
(function(){
  var a = b = 10; (b前面没有var)
})()
console.log( b ); //此时b的值为10
</script>

/* b的写法相当于全局有个b */
<script>
var b = 10
(function(){
  var a = b = 10;
})()
console.log( b ); //此时b的值为10
</script>

JS有变量提升的机制(变量悬挂声明)

javascript 复制代码
/* 这样打印会报错 */
<script>
function fun(){
  console.log(str)
}
</script>

/* 这样写会打印出undefined */
<script>
function fun(){
  console.log(str)
  var str = '11111'
}
</script>

/* 上面那样写是因为变量提升,其实就相当于这样写 */
<script>
function fun(){
  var str
  console.log(str) // 所以才会打印出undefined
  str = '11111'
}
</script>

<script>
var name = 'a';
(function(){
  if(typeOf name == 'undefined'){
    var name = 'b';
    console.log('111' + name); // 最终会打印出111b(因为name会变量提升)
  }else{
    console.log('222' + name);
  }
})()
</script>

声明变量的优先级 > 声明普通函数 > 参数 > 变量提升

javascript 复制代码
<script>
function fun(){
  var a = 10;
  function a(){}
  console.log( a ); // 打印10
}
fun()
</script>

<script>
function fun(){
  var a = 10;
  var a = function (){}
  console.log( a ); // 打印出函数
}
fun()
</script>

<script>
function fun(){
  console.log( a ); // 打印出函数
  var a = 10;
  function a(){}
}
fun();
</script>

<script>
function fun(a){
  console.log( a ); // 打印出100
  var a = 10;
}
fun(100);
</script>

<script>
function fun(a){
  console.log( a ); // 打印出函数
  function a (){};
}
fun(100);
</script>

<script>
function fun(a){
  var a = 10;
  function a (){};
  console.log( a ); // 打印出10
}
fun(100);
</script>
  1. JS对象

对象是通过new操作符构建出来的,所以对象之间不相等(除了引用外)

javascript 复制代码
<script>
console.log( [1,2,3] === [1,2,3] ) // false
</script>

对象要注意引用的时候

javascript 复制代码
<script>
var obj1 = {
  a : 1
};
var obj2 = obj1;
console.log(obj1,obj2); // 打印出的值是一样的

obj2.a = 'aaaaaa';
console.log(obj1,obj2) // 打印出的值依然是一样的

var arr1 = [1,2,3];
var arr2 = arr1;
console.log( arr1 === arr2 ); // 打印出true
</script>

对象的key永远都是字符串

javascript 复制代码
<script>
var obj1 = {
  a: 1,
  '张三': '你好'
}
for (var k in obj1){
  console.log(k); // a 张三
  console.log( typeof k ); // string string
}
</script>

<script>
var o = {
  b: 'bbbb'
}
var obj1 = {
  a: 1,
  '张三': '你好'
}
obj1[o] = '123'
for (var k in obj1){
  console.log(k); // a 张三 [object object]
  console.log( typeof k ); // string string string(因为此时的obj1已经变成obj1={a:1, '张三': '你好', '{}':'123'}
}
</script>

<script>
var a = {}
var b = {
  key: 'a',
}
var c = {
  key: 'c',
}
a[b] = '123'; // 此时a就会变成 var a = { '[Object Object]': '123'}
a[c] = '456'; // c其实也是'[Object Object]',那么它的456就会覆盖前面的123
console.log( a[b] ); //打印的结果是456
/* 其实就相当于 */
let m = {}
m.a = 1;
m.a = 2;
console.log( m.a ); // 打印出的结果肯定是2
</script>

对象如何找属性和方法(每一个对象都是通过构造函数构建出来的)

先在对象本身找 ==> 构造函数中找 ==> 对象原型中找 ==> 原型对象中找 ==> 对象上一层原型中找
每一个函数都自带一个prototype属性,也就是我们说的原型

原型和原型链-CSDN博客

javascript 复制代码
/* 综合题目1 */
function Foo(){
  getName = function(){console.log(1)} //注意,此处的getName是全局的,是window.getName
  return this; // 也就是window
}
Foo.getName = function(){console.log(2)}
Foo.prototype.getName = function(){console.log(3)}
var getName = function(){console.log(4)}
function getName(){
  console.log(5)
}
Foo.getName(); // 2
getName; // 4
Foo().getName(); // 1 ------>相当于是window.getName()
getName(); // 1
new Foo().getName(); // 3

/* 综合题目2 */
var o = {
  a: 10,
  b: {
    fn: function(){
      console.log( this.a ); // b里面没有a,所以打印的结果是undefined
      console.log( this ); // 打印出b这个对象{fn: f}
    }
  }
}
o.b.fn();

/* 综合题目3 */
window.name = 'xiongxinyu';
function A(){
  this.name = 123;
}
A.prototype.getA = function(){
  console.log(this)
  return this.name + 1;
}
let a = new A();
let funcA = a.getA;
funcA(); // 结果是打印了window,返回了xiongxinyu1

/* 综合题目4 */
var length = 10;
function fn(){
  return this.length + 1;
};
var obj = {
  length: 5,
  test1: function(){
    return fn();
  }
}
obj.test2 = fn; 
/* 执行完上一行代码,相当于obj变成了
var obj = {
  length: 5,
  test1: function(){
    return fn();
  },
  test2: function fn(){
    return this.length + 1;
  };
} */
console.log( obj.test1() ); // 这是一个闭包的过程,this指向的是window,所以最后结果是11
console.log( fn() === obj.test2() ); // false // fn()返回的是11,obj.test2中的this代表的是obj,所以返回的是6
console.log( obj.test1() == obj.test2() ); // false 11并不等于6
相关推荐
拾光拾趣录4 分钟前
CSS 深入解析:提升网页样式技巧与常见问题解决方案
前端·css
莫空00005 分钟前
深入理解JavaScript属性描述符:从数据属性到存取器属性
前端·面试
guojl6 分钟前
深度剖析Kafka读写机制
前端
FogLetter7 分钟前
图片懒加载:让网页飞起来的魔法技巧 ✨
前端·javascript·css
Mxuan7 分钟前
vscode webview 插件开发(精装篇)
前端
Mxuan8 分钟前
vscode webview 插件开发(交付篇)
前端
Mxuan9 分钟前
vscode 插件与 electron 应用跳转网页进行登录的实践
前端
拾光拾趣录10 分钟前
JavaScript 加载对浏览器渲染的影响
前端·javascript·浏览器
Codebee10 分钟前
OneCode图表配置速查手册
大数据·前端·数据可视化
然我10 分钟前
React 开发通关指南:用 HTML 的思维写 JS🚀🚀
前端·react.js·html