9月17日 JavaScript基础补充知识

JavaScript基础补充知识

面试题:

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

答:延迟加载:async、defer
<script defer type="text/javascript" src='script.js'></script>
defer : 等html全部解析完成,才会执行js代码,顺次执行js脚本。
async : async是和html解析同步的(一起的),不是顺次执行js脚本(谁先加载完谁先执行)。

2. JS数据类型和考题

  1. 数据类型:
  • 基本类型:string(字符串)、number(数值)、boolean(布尔)、undefined(未定义)、null、symbol、bigint
  • 引用类型:object
  1. 考题:
console.log( true + 1 );     			//2  布尔隐式转换成数值类型,true为1,false为0
console.log( 'name'+true );  			//nametrue  字符串+任何为字符串
console.log( undefined + 1 ); 		//NaN 数值类型
console.log(typeof null);   //  object   null为特殊的object类型
console.log(typeof NaN);  //number
console.log( typeof undefined ); //undefined

数据类型隐式转换问题:

  • 布尔和数字或者纯布尔加(+),布尔会自动转换成数值类型
  • 字符串和任何类型加(+),其他类型都会转换成字符串
    NaN是一个数值类型,但是不是一个具体的数字。

3. null和undefined区别

  1. 作者在设计js的时候先设计的null(为什么设计了null:最初设计js的时候借鉴了java的语言)
  2. 表示无的值,最好不是对象,最好是一个基本类型。null会被隐式转换成0,很不容易发现错误。
  3. 先有null(不应该有值)后有undefined(缺少值),出来undefined是为了填补之前的坑。
  • 具体区别:JavaScript的最初版本是这样区分的:null是一个表示"无"的对象(空对象指针),转为数值时为0;undefined是一个表示"无"的原始值,转为数值时为NaN。

4. JS作用域考题

  1. 除了函数外,js是没有块级作用域。
  2. 作用域:作用的区域或范围(全局、局部)
  3. 作用域链:内部可以访问外部的变量,但是外部不能访问内部的变量。
    注意:如果内部有,优先查找到内部,如果内部没有就查找外部的。
  4. 注意: 声明变量是用var还是没有写(window.)
  5. 注意:js有变量提升的机制【变量悬挂声明】,JS提升所有变量声明,将他们移到其作用域的开头。
  6. 优先级:声明变量 > 声明普通函数 > 参数 > 变量提升
  • 面试的时候怎么看:
  1. 本层作用域有没有此变量【注意变量提升】
  2. 注意:js除了函数外没有块级作用域
  3. 普通声明函数是不看写函数的时候顺序
考题1:
function c(){
	var b = 1;
	function a(){
		console.log( b );     //undefined
		var b = 2;
		console.log( b );   // 2
	}
	a();
	console.log( b );     //  1
}
c(); 
考题2:
var name = 'a';
(function(){     // var name;
	if( typeof name == 'undefined' ){ 
		var name = 'b';
		console.log('111'+name);    // 111b
	}else{
		console.log('222'+name);
	}
})()
考题3:
function fun( a ){
	var a = 10;
	function a(){}
	console.log( a );   //10
}
fun( 100 );

5. JS数组去重

方式1:new set

new Set():去重数组

var arr1 = [1,2,3,2,4,1];
function unique(arr){
	return [...new Set(arr)]   //return (Array.from(new Set(arr))  );
}
console.log(  unique(arr1) );
方式2:indexOf

indexOf():查找,有返回下标,没有返回-1

var arr2 = [1,2,3,2,4,1];
function unique( arr ){
	var brr = [];
	for( var i=0;i<arr.length;i++){
		if(  brr.indexOf(arr[i]) == -1 ){
			brr.push( arr[i] );      //push() 将参数添加到原数组末尾,并返回数组的长度
		}
	}
	return brr;
}
console.log( unique(arr2) );
方式3:sort

sort():按升序排列数组项

var arr3 = [1,2,3,2,4,1];
function unique( arr ){
	arr = arr.sort();
	var brr = [];
	for(var i=0;i<arr.length;i++){
		if( arr[i] !== arr[i-1]){
			brr.push( arr[i] );
		}
	}
	return brr;
}
console.log( unique(arr3) );

6. new操作符具体做了什么

  1. 创建了一个空的对象
  2. 将空对象的原型,指向于构造函数的原型
  3. 将空对象作为构造函数的上下文(改变this指向)
  4. 对构造函数有返回值的处理判断(如果返回的是基本类型,就忽略,如果返回的是引用类型,就返回return)
function Fun( age,name ){
	this.age = age;
	this.name = name;
}
function create( fn , ...args ){
	//1. 创建了一个空的对象
	var obj = {}; //var obj = Object.create({})
	//2. 将空对象的原型,指向于构造函数的原型
	Object.setPrototypeOf(obj,fn.prototype);
	//3. 将空对象作为构造函数的上下文(改变this指向)
	var result = fn.apply(obj,args);
	//4. 对构造函数有返回值的处理判断
	return result instanceof Object ? result : obj;
}
console.log( create(Fun,18,'张三')   )

7. 闭包

  1. 闭包是什么
    闭包是一个函数加上到创建函数的作用域的连接,闭包“关闭”了函数的自由变量。
  2. 闭包可以解决什么问题【闭包的优点】
  • 内部函数可以访问到外部函数的局部变量
  • 闭包可以解决的问题
	var lis = document.getElementsByTagName('li');
    for(var i=0;i<lis.length;i++){
      (function(i){
        lis[i].onclick = function(){
          alert(i);
        }
        lis[i] = null;     //手动清空
      })(i)
    }
  1. 闭包的缺点
  • 变量会驻留在内存中,造成内存损耗问题。
    解决:把闭包的函数设置为null
  • 内存泄漏【ie】 ==> 可说可不说,如果说一定要提到ie

8. 原型链

  1. 原型可以解决什么问题
    对象共享属性和共享方法
  2. 谁有原型
    函数拥有:prototype
    对象拥有:__ proto__
  3. 对象查找属性或者方法的顺序
    先在对象本身查找 --> 构造函数中查找 --> 对象的原型 --> 构造函数的原型中 --> 当前原型的原型中查找
  4. 原型链
  • 是什么?:就是把原型串联起来
  • 原型链的最顶端是null

9. JS继承有哪些方式

方式1:ES6
class Parent{
	constructor(){
		this.age = 18;
	}
}

class Child extends Parent{
	constructor(){
		super();
		this.name = '张三';
	}
}
let o1 = new Child();
console.log( o1,o1.name,o1.age );
方式2:原型链继承
function Parent(){
	this.age = 20;
}
function Child(){
	this.name = '张三'
}
Child.prototype = new Parent();
let o2 = new Child();
console.log( o2,o2.name,o2.age );
方式3:借用构造函数继承
function Parent(){
	this.age = 22;
}
function Child(){
	this.name = '张三'
	Parent.call(this);
}
let o3 = new Child();
console.log( o3,o3.name,o3.age );
方式4:组合式继承
function Parent(){
	this.age = 100;
}
function Child(){
	Parent.call(this);
	this.name = '张三'
}
Child.prototype = new Parent();
let o4 = new Child();
console.log( o4,o4.name,o4.age );

10. 说一下call、apply、bind区别

  1. 共同点:功能一致
    可以改变函数内的this指向
    语法: 函数.call()、函数.apply()、函数.bind()
  2. 区别:
  • call、apply可以立即执行。bind不会立即执行,因为bind返回的是一个函数需要加入()执行。
  • 参数不同:apply第二个参数是数组。call和bind有多个参数需要挨个写。
  1. 场景:
用apply的情况
var arr1 = [1,2,4,5,7,3,321];
console.log( Math.max.apply(null,arr1) )

用bind的情况
var btn = document.getElementById('btn');
var h1s = document.getElementById('h1s');
btn.onclick = function(){
	console.log( this.id );
}.bind(h1s)

11. 深拷贝和浅拷贝

  1. 共同点:复制
  • 浅拷贝:只复制引用,而未复制真正的值。(同一个地址,一个改变则相互改变)
var arr1 = ['a','b','c','d'];
var arr2 = arr1;

var obj1 = {a:1,b:2}
var obj2 = Object.assign(obj1);
  • 深拷贝:是复制真正的值 (不同引用,两个地址,一个改变,互相不影响)
var obj3 = {
	a:1,
	b:2
}
var obj4 = JSON.parse(JSON.stringify( obj3 ));

//递归的形式
function copyObj( obj ){
	if(  Array.isArray(obj)  ){
		var newObj = [];
	}else{
		var newObj = {};
	}
	for( var key in obj ){
		if( typeof obj[key] == 'object' ){
			newObj[key] = copyObj(obj[key]);
		}else{
			newObj[key] = obj[key];
		}
	}
	return newObj;
}
console.log(  copyObj(obj5)  );

12. 统计字符次数

/*最终返回一个对象
{
	a:3,
	b:2,
	c:2,
	m:1,
}*/

var str = 'abccbaam'; //a3 b2 c2 m1

function fUnique(str){
	//创建一个对象
	var obj = {};

	for(var i=0;i<str.length;i++){

		var key = str[i];

		//如果obj对象没有a ,添加一个a,并且赋值为1
		if(  !obj[key]  ){

			obj[key] = 1;

		//如果obj对象有对应的key了,就让值+1
		}else{
			obj[key] += 1;

		}

	}

	//返回最终结果的对象
	return obj;	
}

console.log(   fUnique(str)   );

13. 找出字符串出现最多次数的字符以及次数

var str = 'aaabbbbbccddddddddddx';
var obj = {};
for(var i=0;i<str.length;i++){
	var char = str.charAt(i);
	if( obj[char] ){
		obj[char]++;
	}else{
		obj[char] = 1;
	}
}
console.log( obj );
//统计出来最大值
var max = 0;
for( var key in obj ){
	if( max < obj[key] ){
		max = obj[key];
	}
}
//拿最大值去对比
for( var key in obj ){
	if( obj[key] == max ){
		console.log('最多的字符是'+key);
		console.log('出现的次数是'+max);
	}
}

14. 解析url参数

//最终返回的结果肯定是一个对象
function fParseQueryString(url){

	var obj = {};

	var urls = url.split('?');

	var arr = urls[1].split('&');

	for(var i=0,len=arr.length;i<len;i++){
		//brr[0] 就是对象的key【属性名】
		//brr[1] 就是属性对象的value值
		var brr = arr[i].split('=');

		obj[brr[0]] = brr[1];

	}

	return obj;

}	

console.log( fParseQueryString('https://www.baidu.com/s?wd=js&rsv_spt=1&rsv_iqid=0xfa41b9e2000013a3&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_sug3=4&rsv_sug2=0&rsv_btype=i&inputT=397&rsv_sug4=855') );
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值