JavaScript基础学习

JS

基础类型

null是一个为空的object
使用typeof检查null,返回object

undefined为未赋值的变量
使用typeof检查undefined,返回undefined

类型转换

parseInt 转成整数

parseInt(3.14) //3
parseInt('120px') //120
parseInt('rem120') //NaN

parseFloat 转成浮点数
Number强制转换

this

this指向一个对象,称为函数执行的上下文对象
以函数形式调用,this→window
以对象形式调用,this→obj
以构造函数形式调用时,this→所new出来的obj
普通setTimeout声明方式,this指向window,箭头函数指向外层作用域(父执行上下文)对象

//箭头函数this指向
var x =11;
var obj = {
	x:22,
	say: ()=>{console.log(this.x);},
	get: function(){
		var test = () =>{console.log(this.x);}
		return test();
	},
	set: ()=>{
		var tst = () =>{console.log(this.x);}
		return tst();
	}
}
obj.say();//11 箭头函数没有this,say指向obj,obj的父执行为window
obj.get();//22 箭头函数没有this,test指向get(正常申明),get的父执行为obj.set();//11 箭头函数没有this,tst指向set同样没有this,set指向obj,obj的父执行为window

arguments

封装实参的对象arguments是一个类数组对象
如何将类数组对象转化为数组

//ES5
Array.prototype.slice.call(arguments)
//ES6
[...arguments]

在调用函数时,所传递的实参都会在arguments中保存
arguments.callee指向当前函数对象
箭头函数没有arguments对象

数组运算

冒泡排序

var arr = [1,2,3,4,2,1];
for (let i = 0;i <= arr.length -1; i++){ //外循环管趟数
	for(let j=0; j<=arr.length - i -1; j++){ //内循环管交换次数
		if(arr[j] < arr[j+1]){
			let temp = arr[j];
			arr[j] = arr[j+1];
			arr[j+1] = temp ;
		}
	}
}

作用域链

链式查找 = 就近原则

function f1(){
	let num = 123;
	function f2(){
		console.log(num);
	}
}
let num = 456;
f1(); //输出的num为123

闭包原理

function a(){
   x =123;
   function b(){
   	console.log(x);//123
   }
   return b;
}
var res = a();//a被调用,执行后链被销毁,返回了b的定义声明
res();//相当于执行了b的定义,链重连 可以访问b、a、go
//b中可以访问到a中的x(每一层ao对象由自己向外scope chain从上到下排列)
//所以a中没法访问b中的内容,a中只能链接自己的ao对象和go对象
//当函数被调用时,会进行执行和销毁,但b被定义时,scopechain和ao对象间的联系又会重连,可以访问到a内的内容

造成内存泄漏:

  • 闭包
  • 意外的全局变量
  • 被遗忘的定时器
  • 脱离dom的引用

预解析

js引擎运行js分两步:
①预解析
变量提升:把变量声明提升到当前作用域最前
函数提升:把函数声明提升到当前作用域最前
预解析:1.创建ao(函数内部)/go(全局)对象
2.寻找形参和变量声明 值为undefined
3.实参形参值统一
4.函数体里找函数声明 值赋予函数体
②顺序执行代码

f1();
function f1(){
	var a = b = c = 9;
	console.log(a);
	console.log(b);
	console.log(c);
}
console.log(c);
console.log(b);
console.log(a);
//以上代码的真实执行状态为:
function fa(){
	var a = 9; //集体赋值的正确写法为 var a = 9 ,b=9;
	b = 9; //没有声明直接赋值,算作全局变量
	c = 9;
	console.log(a); //9
	console.log(b); //9
	console.log(c); //9
}
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //报错 变量未定义(局部变量)

构造函数

构造函数与普通函数没有区别,习惯上构造函数首字母大写
调用时,构造函数用new关键字
new时:
①开辟新的空间新建一个obj
②将this指向新建的obj
③执行func里的代码
④将新建的obj返回

function Person (name){
	this.name = name; //将全局变量赋值给this(obj)变量
}
var per = new Person("konan");//per被称为Person类的实例

为了防止每次新建实例就新建一个重复函数,并不污染全局作用域,将函数放入共同的prototype对象中
新建的实例中,如果没有对应的key值会去prototype(proto)中寻找,如果有就不会去找

function Person (name){
	this.name = name; 
}
Person.prototype.func = function(){};
Person.a = "123";
var per = new Person("konan");//per.a = "123"
per.func();
var per2 = new Person("");
var per2.a = "456";//per2.a = "456"

对象中是否存在某个元素

//in方法当自身没有但是原型有也会返回true
console.log("123" in per);//true
//hasOwnProperty只返回自身是否有
cosole.log(per.hasOwnProperty("123"));//false

垃圾回收

当一个对象没有任何的变量或属性对他进行引用,浏览器自动进行回收

DOM

document object model 文档对象模型,通过DOM接口改变网页的内容解构和样式
D:整个HTML文档
O:将整个网页中每一部分转换成一个对象
M:表示对象间的关系
节点Node:网页中的每一部分都是一个节点
document就是文档节点,指向整个网页

var btn = document.getElementById();
btn.innerHTML = "";//修改文字
btn.onclick = function() {};//增加点击事件

innerHTML 和 createElement的创建效率差

//innerHTML字符拼接方式
var inner = document.querySelector('.inner');
for(var i =0; i<=100; i++){
	inner.innerHTML += '<a href="#"></a>'; //innerHTML字符拼接方式最慢 需要3000ms左右
}
//createElement方式
for(var i =0; i<=100; i++){
	var a = document.createElement('a');
	inner.appendChile(a);//createElement方式需要大概20ms左右
}
//innerHTML 数组方式
var arr = [];
for(var i =0; i<=100; i++){
	arr.push('<a href="#"></a>'):
}
inner.innerHTML = arr.join('');//join转化成字符串 最快 只需10ms以内

DOM事件流
给div添加一个点击事件
两种传播顺序
捕获阶段:从父找到子(目标div)
冒泡阶段:从子回到父
在这里插入图片描述
js代码中只能执行其中一个阶段
默认为冒泡阶段

事件对象
跟事件相关的一系列的信息数据的集合
event是一个形参
event兼容问题:

e = e || window.event //ie678

e.target返回的是触发事件的对象(元素)
this返回的是绑定事件的对象(元素)

<ul><li>123<li></ul>
var ul = document.querySelector('ul');
//点击123时
ul.addEventListenr('click', function(e){
	console.log(this); //this→ ul
	console.log(e.target); //e.target→ li
}

BOM

浏览器对象模型
将浏览器作为一个对象
顶级为window

同步与异步

同步任务放在主线程执行栈
异步任务(回调函数)放在消息队列
执行完同步才会去执行异步(异步进程处理)
事件循环机制:执行完同步后也会循环检查是否队列里有异步任务
EventLoop
在这里插入图片描述
执行代码时将内容压入调用栈,回调函数压入消息队列,promise后续处理内容(then)压入微任务队列,调用栈被清空会才回去按照微任务→消息队列顺序执行
回顾

//输出顺序4 1 3 5 2
var p = new Promise(resolve =>{ //调用栈中加入的微任务会立即执行
	console.log(4);
	resolve(5);
})
function fun1(){
	console.log(1)
}
function fun2(){
	setTimeout (()=>{
		console.log(2);
	},0);//异步操作进入消息队列等调用栈及微任务清空后才会执行
	
	fun1();//执行后从调用栈弹出
	console.log(3);
	
	p.then(resolve=>{
		console.log(resolve);//进入微任务队列,等待调用栈清空后执行
	})
}
fun2();

本地存储

sessionStorage
localStorage

sessionStorage.setItem(key, value)
sessionStorage.getItem(key)
sessionStorage.removeItem(key)
sessionStorage.clear()

jQuery

对原生js封装的库
$是jQuery的别称,是jquery的顶级对象

//等待DOM结构渲染完毕即可执行内部代码,等同于原生js的DOMContentLoaded
$(function () {
})

jQuery对象与DOM对象不同,jquery用$把DOM元素进行了封装,存在形式为一个伪数组
相互不能混用方法和属性
jQuery对象与DOM对象转换

//DOM → jQuery
var myVideo= document.querySelector('video');
$(myVideo)
//jQuery → DOM
$('video')[0].play();
$('video').get(0).play();
正则表达式
var reg = new RegExp("a", "i"/"g"); // i:忽略大小写 g:全局模式
//等同于 reg = /a/i
var str = "abc";
reg.test(str); //true

reg = /a|b/  == /[ab]/; //a或b
/[a-z]/ 任意小写字母
/[A-z]/ 任意字母
/a[bd]c/ abc或adc
/[^ab]/ 除了ab

call & apply & bind

共同点:能够调用函数,能够改变this的指向

//call使用
let a = {
   func(x) {
   	console.log(x)
   }
};
let b ={name:""};
a.func.call(b,"x");//将a内的函数this指向b 并传参x

区别
call/apply直接调用函数
bind返回函数,需要再执行调用指令

//apply
a.func.call(b,"x","y");
a.func.apply(b,["x","y"]);//需要数组形式传参
let c = a.func.bind(b,"x","y");
c();//需要调用

知识试题
1.预编译/预解析
2.this指向/箭头函数的this
3.图片懒加载(data-src)
4.数据扁平化

代码试题
1.赋值/浅拷贝/深拷贝
参考
2.防抖/节流

//防抖:一定时间内不再执行 才执行对应功能 否则清楚计时器 重新计时
function debounce(delay){
	let timer;
	return function (value){
		clearTimeout(timer);
		timer = setTimeout( ()=>{
			console.log(value);
		},delay)
	}
}
var input = document.getElementById('input');
var func = debounce(2000);
input.addEventListener('keyup', function(e){
	func(e.target.value);
})
//节流:一定时间内 再执行对应功能
function throttle(delay){
	let timeOut;
	return function(){
		if(!timeOut){
			timeOut = setTimeout(()=>{
				fun();
				timeOut = null;
			},delay)
		}
	}
}

todo 图片懒加载与节流防抖的结合应用

闭包实现单例模式

var createLogin = function (a,b,c) {
	console.log(a,b,c);
	var div = document.createElement("div");
	div.innerHTML = '我是登录点击显示内容';
	div.style.display = 'none';
	document.body.appendChild(div);
	return div
}
var getSingle = function (fn) {
	var result;
	return function () {
		return result || (result = fn.call(this,arguments));
	}
}
var create = getSingle(createLogin);
document.getElementById("loginButton").onclick = function () {
	var loginLay = create(1,2,3);
	loginLay.style.display = 'block';
}

实现手写Array.prototype.map方法

function mapfunc (arr, mapCallback){
	if(!Array.isArray(arr) || !arr.length || typeof mapCallback !== 'function'){
		return []
	} else {
		let result = [];
		let len = arr.length;
		for(let i=0; i < len; i++){
			result.push(mapCallback(arr[i],i,arr))
		}
		return result;
	}
}

var arr = [1,2,3];
var test = mapfunc(arr,(item,index)=>{
	return item * 2;
})
console.log(test);

//prototype的使用方式
var arr = [1,2,3];
var test = arr.map((item,index)=>{
	return item * 2;
})
console.log(test);


3.数据扁平化

4.优化if嵌套
提前退出& 提前返回

const printAnimalsDetails = ({type, name, gender} ={}) => {
	if(!type) return 'no type'
	if(!name) return 'no name'
	if(!gender) return 'no gender'
	return `${name}` is a ${gender} - ${type}`
}

5.slice(start,end) 不影响原数组 返回新数组,包含start不包含end

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值