javascript入门知识概览-未写完

javascript入门总结

1 javascript历史

javascript是一门用来描述网页行为的脚本语言。
javascript由网景创建,商标由sun公司持有。
javascript由三部分组成ecmascript、dom、bom。
es标准的部分历史:
由ecma-262技术委员会发布
99年12月发布的es3.0,被几乎所有浏览器支持
07年10月发布的es4.0草案由于分歧很大被搁置
08年7月将es4.0中对es3.0优化改善且无争议的一部分发布为es3.1即es5
09年12月 es5.0正式发布
12年 所有的现代浏览器都支持es5.1,旧版本的都支持es3
15年6月17日 es6.0发布,官方命名为es2015,并规定以后每年发布一次以es+年份为命名的es版本

2 javascript基本句法

js区分大小写
js每句话以分号结尾(强烈建议)
变量先声明再使用
在js文件头部使用“use strict”声明进入严格模式

3 javascript 变量、常量、方法

js中使用var、let定义变量、const定义常量;let和const在es2015中发布。

3.1 使用var定义变量

在全局作用域下定义的变量即为全局变量,可以用变量名和window.变量名访问
在函数中不用关键字定义变量,也为全局变量
使用var定义变量会存在变量提升问题

	var test1 = 1;
	function fun1(){
		test2 = 2; //定了一个名为test2的全局变量 严格模式下会抛出ReferenceError异常
	}
	fun1()
test1和test2都为全局变量,在全局作用域下均能被访问。
	var test1 = 1;
	function fun1(){
		var test1 = 2; //在fun1函数作用域内定义了一个名为test1的变量
	}
	fun1();
	var test3 = 3;
	function fun2(){
		test3 = 4; //将全局变量重新赋值 
	}
	fun2();

3.2 使用let定义变量

在es6中let正式发布,使用let定义的变量不存在变量提升的问题。
使用let定义变量时不能先使用后定义。
使用let定义变量时不能重复定义相同字面量的变量。
使用let定义变量后存在严格块级作用域,不能在作用域外使用该变量。

3.3 使用const定义常量

使用const定义常量时必须先定义再使用。
使用const定义常量时不能重复定义相同字面量的常用。
使用const定义常量时必须赋值。
使用const定义常量后值不可更改。
使用const定义的常量存在严格的块级作用域,不能在作用域外使用该变量。

3.4 使用function定义方法

在js中有2种方式定义方法
第一种使用function关键字声明式
function fun1(){};
第二种变量声明式,即函数字面量式
var fun1 = function(){}
不要使用Function构造函数去定义方法

3.5 变量提升

js代码在浏览器中是先解释后执行,使用var定义变量存在变量提升的问题。
所有的声明都会提升到作用域的最顶上去。
同一个变量只会声明一次,其他的会被忽略掉或者覆盖掉。
函数声明的优先级高于变量声明的优先级,并且函数声明和函数定义的部分一起被提升。

	console.log(a);
	var a = 1;
	//以上代码等同于
	var a;
	console.log(a);
	a = 1;
	//因为变量a的声明被提升到了作用域顶端

直接使用function关键字声明的函数会直接将函数内容也提升到作用域顶端

	fnA();
	function fnA(){
		console.log(1);
	}
	//等同于
	function fnA(){
		console.log(1);
	}
	fnA();
	//控制台输出1

使用字面量方式定义函数

	fnb();
	var fnb = function(){};
	//同理使用var定义变量,等同于以下代码
	//因声明时fnb不是方法 控制台会报 fnb is not a function
	var fnb;
	fnb();
	fnb = function(){};

4 javascript常用数据类型及分类

4.1 javascript数据类型

Number:数字
String:字符串
Boolean:布尔类型
null:空
undefined:未定义
Symbol
BigInt
Object 对象
Function 方法
Array 数组
Date 日期
Regexp 正则表达式
我们常用的数据类型有Number、String、Boolean、Function、Array、Object、Date

4.2 数据类型分类

根据存储方式分为基本数据类型(值类型)和对象(引用类型)
值类型:name和val均在栈中 数据大小固定
常用的值类型有数字(Number)、字符串(String)、布尔类型(Boolean)。
引用类型:name和指针存在栈中,val存在堆中 堆中数据大小不固定
常用的引用类型有数组(Array)、对象(Object)。

4.3 浅拷贝和深拷贝

浅拷贝:将A赋值给B,A变化时B跟着变化则为浅拷贝,浅拷贝是相对于深拷贝而言。
深拷贝:将A赋值给B,A变化时B不变则为深拷贝

4.3.1 深拷贝实现方式

JSON.parse(JSON.stringify(arr1));
递归拷贝

	function deepClone(obj){
	    let objClone = Array.isArray(obj)?[]:{};
	    if(obj && typeof obj==="object"){
	        for(key in obj){
	            if(obj.hasOwnProperty(key)){
	                //判断ojb子元素是否为对象,如果是,递归复制
	                if(obj[key]&&typeof obj[key] ==="object"){
	                    objClone[key] = deepClone(obj[key]);
	                }else{
	                    //如果不是,简单复制
	                    objClone[key] = obj[key];
	                }
	            }
	        }
	    }
	    return objClone;
	}    
	let a=[1,2,3,4],
	    b=deepClone(a);
	a[0]=2;
4.3.2 Object.assign

根据mdn种的定义,Object.assign() 方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。
Object.assign:一层支持深拷贝,多层则不支持
Object.assign在复制时,假如源值是一个对象的引用,它仅仅只会复制其引用值。
翻译一下这句话就是说假如源值是值类型,则不会存在A变B也变的情况,假如源值是引用类型,则仅仅只是复制其指针地址,会存在A变B也变得情况。用以下代码演示:

	var x = {a:1};
	var y = Object.assign({},x);
	x.a = 2;
	y.a; //此时y.a的值为1
	
	var m = {a:{b:1}};
	var n = Object.assign({},m);
	m.a.b = 2;
	n.a.b; //此时n.a.b的值也为2

5 javascript事件发生机制及代理

5.1 事件捕捉和事件冒泡

事件捕捉和事件冒泡是为了解决web中事件发生的顺序机制而提出的解决方案。其中事件捕捉是网景提出的,事件冒泡是微软提出的。事件捕捉和事件冒泡的机制如下图:
事件捕捉和事件冒泡
事件冒泡可以形象地比喻为把一颗石头投入水中,泡泡会一直从水底冒出水面。不过事件冒泡的事件流模型被所有主流的浏览器兼容。

5.2 事件委托

事件委托也可以称为事件代理,是指当我们有动态加入的节点或者为减少事件绑定消耗时将事件绑定在父元素节点上然后根据evt的target属性和currentTarget属性去判断事件发生时的目标节点的一种处理方式。用以下代码演示:

	<ul id="color-list">
	    <li>red</li>
	    <li>yellow</li>
	    <li>blue</li>
	    <li>green</li>
	    <li>black</li>
	    <li>white</li>
	</ul>
	//假如我们要给li绑定事件的话
	//普通
	var colors = color_list.getElementsByTagName('li');
	for(var i=0;i<colors.length;i++){
		colors[i].addEventListener('click',showColor,false);                               
	};
	function showColor(e){
	   var x = e.target;
	   alert("The color is " + x.innerHTML);
	};
	//使用事件代理
	var color_list = document.getElementById('color-list');
	color_list.addEventListener('click',showColor,false);
	function showColor(e){
		var x = e.target;
	    	if(x.nodeName.toLowerCase() === 'li'){
	            alert('The color is ' + x.innerHTML);
	        }
	    }
	}

6 javascript执行机制

6.1 同步、异步

js是单线程执行单线程就意味着,所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。
如果排队是因为计算量大,CPU忙不过来,倒也算了,但是很多时候CPU是闲着的,因为IO设备(输入输出设备)很慢(比如Ajax操作从网络读取数据),不得不等着结果出来,再往下执行。
JavaScript语言的设计者意识到,这时主线程完全可以不管IO设备,挂起处于等待中的任务,先运行排在后面的任务。等到IO设备返回了结果,再回过头,把挂起的任务继续执行下去。
于是,所有任务可以分成两种: 同步任务(synchronous),同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务 异步任务(asynchronous),异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。
同步异步
1. 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
2. 当Event Table中指定的事情完成时,会将这个函数移入Event Queue。
3. 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行。
4. 上述过程会不断重复,也就是常说的Event Loop(事件循环)。
5. js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

6.2 宏任务、微任务

macro-task(宏任务):包括整体代码script,setTimeout,setInterval     micro-task(微任务):Promise,process.nextTick   不同类型的任务会进入对应的Event Queue。   事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。 接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。
 宏、微

	console.log('1');
	setTimeout(function() {
	    console.log('2');
	    process.nextTick(function() {
	        console.log('3');
	    })
	    new Promise(function(resolve) {
	        console.log('4');
	        resolve();
	    }).then(function() {
	        console.log('5')
	    })
	})
	process.nextTick(function() {
	    console.log('6');
	})
	new Promise(function(resolve) {
	    console.log('7');
	    resolve();
	}).then(function() {
	    console.log('8')
	})
	
	setTimeout(function() {
	    console.log('9');
	    process.nextTick(function() {
	        console.log('10');
	    })
	    new Promise(function(resolve) {
	        console.log('11');
	        resolve();
	    }).then(function() {
	        console.log('12')
	    })
	})
/*
1、 第一轮事件循环流程分析如下:
    整体script作为第一个宏任务进入主线程,遇到console.log,输出1。
    遇到setTimeout,其回调函数被分发到宏任务Event Queue中。我们暂且记为setTimeout1。
    遇到process.nextTick(),其回调函数被分发到微任务Event Queue中。我们记为process1。
    遇到Promise,new Promise直接执行,输出7。then被分发到微任务Event Queue中。我们记为then1。
    又遇到了setTimeout,其回调函数被分发到宏任务Event Queue中,我们记为setTimeout2。

    宏任务Event Queue   微任务Event Queue
    setTimeout1         process1
    setTimeout2         then1

    上表是第一轮事件循环宏任务结束时各Event Queue的情况,此时已经输出了1和7。
    我们发现了process1和then1两个微任务。
    执行process1,输出6。
    执行then1,输出8。

    好了,第一轮事件循环正式结束,这一轮的结果是输出1,7,6,8。

2、 那么第二轮时间循环从setTimeout1宏任务开始:

    首先输出2。接下来遇到了process.nextTick(),同样将其分发到微任务Event Queue中,
记为process2。new Promise立即执行输出4,then也分发到微任务Event Queue中,记为then2。

    宏任务Event Queue     微任务Event Queue
    setTimeout2           process2
                        then2

    第二轮事件循环宏任务结束,我们发现有process2和then2两个微任务可以执行。
        输出3。
        输出5。
        第二轮事件循环结束,第二轮输出2,4,3,5。

3、 第三轮事件循环开始,此时只剩setTimeout2了,执行。
        直接输出9。
        将process.nextTick()分发到微任务Event Queue中。记为process3。
        直接执行new Promise,输出11。
        将then分发到微任务Event Queue中,记为then3。

    宏任务Event Queue     微任务Event Queue
                            process3
                            then3     
    第三轮事件循环宏任务执行结束,执行两个微任务process3和then3。
        输出10。
        输出12。
        第三轮事件循环结束,第三轮输出9,11,10,12。

    整段代码,共进行了三次事件循环,完整的输出为1,7,6,8,2,4,3,5,9,11,10,12。
*/

7 javascript原型、原型链以及继承

js不同于java的很重要一点,js是基于原型、原型链来实现继承的,而java是基于类来实现继承。

7.1 原型、原型链

js中的对象都来源于Object。
js中的每个对象(Object)都有一个属性指针prototype。
它指向该对象的原型(Object.prototype);Object.prototype则为对象的原型。
每个对象实例都有一个属性_proto_,它指向该对象的原型;
而该原型对象也有一个属性_proto_指向自己的原型对象,
层层向上直到一个原型对象的_proto_指向null。
依据es标准,应该使用someObject.[[Prototype]]表示指向someObject的原型
_proto_是许多浏览器实现的属性 
如下图:

原型链
js对象的属性是动态的,可以随时随地添加。
当试图访问一个对象的属性时,js不仅仅在该对象上查找,也在该对象的原型对象上查找。
当没有找到该属性时,就是在该对象的原型对象的原型对象上查找,层层向上直到找到或者找到null为止。

7.2 继承

7.2.1 根据原型链继承
function Animal(name,age){
	this.name = name;
	this.age = age;
	this.eat = function(food){
		console.log(food);
	}
}
function Bird(){
	this.leg = 2;
	this.fly = function(){
	}
} 
function Lion(){
	this.leg = 4;
	this.run = function(){
	}
}
Bird.prototype = new Animal();
Bird.prototype.constructor = Bird;

Lion.prototype = new Animal():
Lion.prototype.constructor = Lion;

var bird1 = new Bird("test1",2);
var lion1 = new Lion("test2",4);

8 闭包和this指向

参考1:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
参考2:https://www.cnblogs.com/shcrk/p/9325779.html

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值