首页 > 其他分享 >【前端】【ES5】【JS的基本使用】

【前端】【ES5】【JS的基本使用】

时间:2022-10-08 13:45:18浏览次数:52  
标签:function ES5 console log 对象 前端 JS var obj

【前端】【ES5】【JS的基本使用】

一、前概

	首先我们需要明白js是一门解释型(解释一行执行一行)面向对象的编程语言,在这个前提下,我们再继续下面的文档阅读。
	面向对象是一种思想,目前主流实现这种思想的有两种方式,一种是类继承,一种是实现继承,js就是通过原型链进行的实现继承。
	
	结构:
	1.面向对象分类
	2.变量
	3.js的执行过程
	4.作用域和作用域链
	5.闭包与立即执行函数
	6.原型和原型链
	7.继承原型和原型链
	7.继承面向对象设计
注:"use strict"; 使用严格模式

二、变量

2.1、变量分类

2.1.1、基本类型

Number  var num =1;
String  var str = "qw";
Boolean var bool = true;
null
undefined

2.1.2、引用类型

2.1.2.1、包装类
1、示例
Number()、String()、Boolean()
通过这三种构造函数创建包装类
var num = new Number(1);
var str = new String("test");
var bool = new Boolean(true);
2、原始类型如何使用方法的过程
//此时str是原始类型
var str = "ase";
// var str = new String(str) 将str转化为临时的包装对象,这样就可以获取length属性,
str.length = 1;
//调用结束后,此对象销毁
//继续,重新执行此操作: var str = new String(str) 将str转化为临时的包装对象,这个对象是一个新的包装对象,所以length还是3
console.log(str.length) //3  
//var str = new String(str) 给str这个临时对象添加属性len,赋值为2
str.len = 2;
//调用完毕,销毁这个临时对象
//var str = new String(str) 获取len属性 ,但这个新的对象里面没有len属性,所以值为undefined
console.log(str.len) //undefined
//调用完毕,销毁该临时对象
2.1.2.2、其他
Object
Array
Function
Date
RegExp
引用类型都是对象,函数也是对象,他们的原型最终都是Object的实例
function Person(){}
var obj = new Person();
var p = typeof Person   //typeof 对函数做了特殊处理,本质上也是对象
var t1 = obj instanceof Person
var t2 = obj instanceof Object
console.log(obj,p,t1,t2)

2.2、变量的传值

基本类型 按值传递  
引用类型 共享传递(本质上也是按值传递,只不过这个值是对象的引用地址)

三种传值策略:
--按值传递(call by value): 函数的形参是被调用时所传实参的副本。修改形参的值并不会影响实参。
--按引用传递(call by reference):传参时直接将对象的地址传入进去(不像共享传递是copy的对象地址值的副本),当函数内部发生变化时,外部的对象也会跟着变化;正式的说,函数的形参接收实参的隐式引用,而不再是副本。
--共享传递(call by sharing):调用函数传参时,函数接受对象实参引用的副本(既不是按值传递的对象副本,也不是按引用传递的隐式引用)

扩展:通过共享调用(传递一个可以随后变异的对象)来实现类似的效果,在Java,Python和Ruby等语言中使用。

2.2.1、基本类型的值传递

var a = b = 1;
b = 2;
console.log(a)//1
#解释
在第一行的语句里,首先b被赋值为1;然后b将他的值复制了一份给a,所以b值的变化于a无影响

2.2.2、引用类型的共享传递

//第一种  全局
var a = b = {x:1};
b.x = 3;
console.log(a.x)//3
#解释
首先在第一行,b被赋值{x:1}的引用地址值,然后,b将他的值(这个值是{x:1}的引用值)复制了一份给a,此时,a与b同时指向了{x:1}对象,所以当b修改x的值时,a输出x时,也会变成3。
//第二种 函数
//1.
var obj = {
    x: 1
};
function test(o) {
    o.x = 2;
}
test(obj)
console.log(obj.x)//2

//2.
var obj = {
    x: 1
};
function test(o) {
    o = new Object();
    o.x =4;
}
test(obj)
console.log(obj.x)//1
#解释
写这两个例子是想说明共享传递和引用传递的区别,如果js是引用传递的话,那么第二个obj的属性x应该是4。

三、JS执行过程

全局对象(GO对象 global object):
	全局对象,可以理解为window对象
运行期上下文(AO对象 activation object):
	当函数执行时,会创建一个称为执行期上下文的内部对象。一个执行期上下文定义了一个函数执行时的环境,*函数每次执行时对应的执行上下文都是独一无二的*,所以多次调用一个函数会导致创建多个执行上下文,当函数执行完毕,它所产生的执行上下文被销毁。
****查找变量:从作用域链的顶端依次向下查找。
js执行三部曲
#语法分析
#预编译
#解释执行
一步一步执行,有赋值语句的,替换GO对象里的对应属性名的(在函数里就替换AO对象里的)

预编译

#全局预编译(代码执行的前一刻)
1.创建GO对象(执行期上下文)
2.寻找形参和变量声明 将变量和形参名作为GO对象的属性名,值为undefined
3.函数声明  并将函数体赋给 GO里的函数声明

函数预编译(函数执行的前一刻)
1.创建AO对象(执行期上下文)
2.寻找形参和变量声明 将变量和形参名作为AO对象的属性名,值为undefined
3.将实参值和形参相统一  将实参的值赋予形参,将AO对象里的值替换
4.函数声明  并将函数体赋给 AO里的函数声明
(在函数里面找变量的值,会先从AO对象里面去找,如果没有就去GO对象里面去找)

流程示例

var b = 11;
function a(a,b){
    console.log("内1"+a)//function a
    a =10;
    console.log("内1"+b)//undefined
    var a = b = 23;
    function a(){

    }
    function c(){}
    console.log("内2"+a) //23
    console.log("内2"+b) //23
    console.log("内1"+c) //function c
    var c;
}
console.log("外1"+a);//function a
a(1);
var a = 30;
console.log("外2"+a); //30
console.log("外"+b); //11
#解释
1.创建GO对象 Global Object
2.变量声明
GO{
b:undefined
}
3.函数声明
GO{
b:undefined
a:function a(a,b){....}
}
#####解释到这一行 console.log("外1"+a);######
#####var b =11######
GO{
b:11
a:function a(a,b){....}
}
#####a(1)######函数预编译
4.函数预编译,创建AO对象 Activation Object
5.变量声明和形参
AO{
a:undefiend
b:undefiend
c:undefined
}
6.形参和实参统一
AO{
a:1
b:undefiend
c:undefined
}
7.函数声明
AO{
a:function a(){}
b:undefiend
c:function c(){}
}
8.解释执行
#####console.log("外1"+a);######
#####a=10;######
AO{
a:10
b:undefiend
c:function c(){}
}
#####console.log("内1"+b)######
##### var a = b = 23;######
GO{
b:11
a:function a(a,b){....}
}
AO{
a:23
b:23
c:function c(){}
}
##### console.log("内2"+a)  console.log("内2"+b) console.log("内1"+c)#####
------------至此,函数执行完毕----------
#####var a =10 ######
GO{
b:11
a:30
}
#####console.log("外2"+a); console.log("外"+b); 

四、作用域和作用域链

4.1、定义

函数有个属性,叫[[scope]],这个属性只有浏览器引擎可以使用,这个就是作用域,里面存储着执行期上下文的集合,通过链式连接,这个链就是作用域链。每个执行期上下文都包含着this、arguments和document,这里的this在非严格模式下,表示windows.但是,GO对象里面只有window和document

4.2、解释

代码:
function a(){
    var aa =1;
    function b(){
            var bb =2;
        fucntion c(){
        var cc =3;
        }
        c()
    }
    b()
}
a()
var glob = 100;

流程示意:
a defined 	a. [[scope] ] -- >	0 : G0
a doing		a. [[scope]] -- >	0 : aA0
                                1 : G0,

b defined 	b. [ [scope]] -- > 	0 : aA0
                                1 : G0
b doing  	b.[ [scope]] -- > 	0 : bAO
                                1 :aA0
                                2 : G0,

c defined 	c.[[scope]] -->		0 : bA0
                                1 : aA0
                                2 : G0
c doing     c.[ [scope]] -- >	0 : cA0
                                1 : bA0,
                                2 : aA0,
                                3 : G0

4.3、图片类似示意

解释:
b在定义的时候,是在a的作用域的基础上构建自己的作用域,所以b作用域里的aAo,和a里的AO是同一个,他们有着相同的引用
当a执行完毕后,就会去掉对自己的AO对象的引用,紧接着b也会去掉对自己的AO对象的引用和对a的AO对象的引用。当a的AO对象没有引用指向它时,就会被销毁。

五、闭包与立即执行函数

5.1、闭包

当外部函数调用对象(函数也是对象)的内部函数时,就叫做闭包,闭包会导致内存泄漏(内存不释放)

闭包的作用

实现公有变量   累加器
可以用作缓存(存储结构)
*****用于封装,属性私有化******
******模块化开发,防止污染全局变量******
代码:
function a(){
    var num = 100;
    function b(){
        num++;
        console.log(num)
    }
    return b;
}
var demo = a();
demo()//101
demo()//102
结构示意
a defined 	a. [[scope] ] -- >	0 : G0
a doing		a. [[scope]] -- >	0 : aA0
                                1 : G0,

b defined 	b. [ [scope]] -- > 	0 : aA0
                                1 : G0
b doing  	b.[ [scope]] -- > 	0 : bAO
                                1 :aA0
                                2 : G0,
GO{
demo:undefined
a:{function}
}
a定义:aAO{
num:undefined
b:{function}
}
a执行与b定义 aAO{
num:100
b:{function}
}
b执行:bAO{

}
解释:
虽然a执行完毕,但是b被return出去并被赋予给demo,demo执行时就是执行b,这就导致了,a的AO对象不被释放;虽然
每执行一次demo,b都会创建自己新的AO对象,但是num值是在a的AO对象里的,而不管b执行多少遍,这些b引用的都是同一个aAo,所以执行一次,num的值就加1

5.2、立即执行函数

5.2.1、定义

针对初始化的函数   可以传参可以有返回值 与普通函数的区别就在于只执行一次就被销毁
(function(){}()) W3C推荐
(function (){})()
,逗号运算符 var a =(1-1,2-1);//1 如果有运算先算前面的,最后将后面的结果返回给a

5.2.2、解释

function test(){}  //这个叫函数声明
var test = function(){} //函数表达式
//只有表达式才能被执行符号声明
test()    //可以
function test(){}()  //报错
test = function(){}() //可以
+function(){}()//可以
-function(){}()//可以
!function(){}()//可以
&&function(){}()//可以  注意前面要加点东西
||function(){}()//可以	注意前面要加点东西
现在再看看
(function (){})()

()括号的作用就是将里面函数变成表达式,使用完后销毁

5.2.3、示例

//闭包里运用立即执行函数
function test(){
    var arr = [];
    for(var i = 0; i < 10; i++){
        (function(j){
            arr[j] = function(){
                console.log(j)
            }
        }(i))
    }
    return arr;
}
var test_arr = test();
for (var j = 0; j < test_arr.length; j++) {
    // console.log(test_arr[j])
    test_arr[j]()
}
//
<ul>
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
</ul>
<script type="text/javascript">
var liArr = document.getElementsByTagName('li');
for (var i = 0; i < liArr.length; i++) {
    (function(j){
        liArr[i].onclick = function(){
            console.log(j)
        }
    }(i))
}
</script>

六、面向对象设计

6.1、对象分类

6.1.1、内部对象

Math Global  可以直接调用,在代码开始前,已实例化好

6.1.2、宿主对象

6.1.2.1、BOM对象
window对象
location对象
navigator对象
screen对象
history对象
6.1.2.2、DOM对象
请看第八章

6.1.3、自定义对象

6.1.3.1、创建对象的几种方式
#对象直接量
var obj = {};
#构造函数
function F(){}
var obj = new F();
#Object.create(原型)

6.1.3.2、构造函数原理(需要先理解原型)
function F(){}
var obj = new F();
在使用构造函数创建对象时,
第一步,构造函数会在一开始隐式的创建一个this对象:this-->{__proto__:F.prototype} 
第二步,会调用this.xxx = xxxx
第三步,隐式的返回this //你也可以显式的返回this,返回其他的也可以,但是必须返回引用类型,如果返回是值类型或null、undefined,则仍然隐式返回this

示例

var obj = { name:"111s"}
Person.prototype = obj

function Person() {
    //this-->{__proto__:obj}
    console.log(this.__proto__)//会将obj打印出来
}
var p = new Person()
console.log(p)

6.2、原型和原型链

6.2.1、定义

函数对象有个属性叫prototype,这个就是原型;
function Grand(){
    this.test ="test"
}
var grand = new Grand();
Father.prototype = grand;
Father.prototype.constructor = Father;//优化,将构造器重新指向Father
function Father(){
    this.name = "father"
}
var father = new Father();
Son.prototype = father
Son.prototype.constructor = Son;//优化,将构造器重新指向Son
function Son(){

}
var son = new Son();
console.log(son)
这种链式调用,叫做原型链

6.2.2、call与apply使用

call和apply作用就是改变构造函数里的this指向,唯一的不同就是参数传递的方式的不同,call支持多个参数,apply只支持一个参数(数组形式)。
第一个参数传对象,可以为null、undefined(非严格模式),但这时this就变成了全局对象了(可以理解为window对象)。
var name = "外面"
var obj = {
    name:"里面",
    show:function (){
        console.log(this.name)
    },
    show_strict:function (){
        "use strict";
        console.log(this.name)
    }
}
obj.show.call(null)
obj.show.call()
obj.show_strict.call(null)//严格模式报错
obj.show_strict.call()//严格模式报错

6.3、继承模式

6.3.1、原型链

缺点:会继承无用的属性和方法

看原型定义里的示例,就是原型链

6.3.2、构造函数

function Person(name,age){
    this.name = name ;
    this.age = age;
}

function Student(name,age,grade){
    Person.call(this,name,age)//节省了代码,但本质上并没有改善效率
    this.grade = grade;
}

var stu1 = new Student("测试",11,11)
console.log(stu1)

6.3.3、共享原型

缺点:一旦需要在原型上增加属性和方法时,其他的也会拥有该属性和方法
function Person(){
    this.last ="测试"
}
Teacher.prototype = new Person();
function Teacher(name,sex){
    this.name = name;
    this.sex = sex;
}
function Student(grade){
    this.grade = grade;
}
Student.prototype = Teacher.prototype; //将Teacher的原型共享给Student
var stu1 = new Student(11)
var tea1 = new Teacher("哈哈",11)

// Student.prototype.show = function(){
// 	console.log(111)
// }

console.log(stu1,tea1)

示意图

解释:在Student的原型上增加了一个show的方法,结果Teacher也拥有了这个方法

6.3.4、圣杯模式

/* 
圣杯模式
 原型链+共享原型+构造函数
 通过构造函数作为中间层,将父类的原型继承,在需要给自己的原型添加属性和方法时,又不会影响父类的原型
 同时,将类的构造器从新指向自己的构造函数
 并将真正继承的原型信息保留下来,以防以后需要
 */
function extend(Class, SuperClass) {
    function F() {};
    F.prototype = SuperClass.prototype;
    Class.prototype = new F();
    Class.constructor = Class;
    Class.prototype.uber = SuperClass.prototype;//可以不写
}


//雅虎
//闭包的高级应用
var inherit = (function() {
    var F = function() {};//使用闭包将变量F私有化
    return function(Class, SuperClass) {
        F.prototype = SuperClass.prototype;
        Class.prototype = new F();
        Class.constructor = Class;
        Class.prototype.uber = SuperClass.prototype;
    }
}())

示例:

function Father() {

}
Father.prototype.name = "测测";

function Son() {

}
extend(Son, Father)
var son = new Son();
Son.prototype.sex = '男';
var father = new Father();
console.log(son)

七、闭包的高级应用

7.1、封装,私有化变量

function Test() {
    var name, sex;
    this.getName = function() {//闭包 私有的作用域未释放
        return name;
    };
    this.setName = function(value) {
        name = value;
    }
}
var obj = new Test();
obj.setName('哈哈');
var test = obj.getName()
console.log(test)

#解释
只能通过getName和setName查看和修改值,直接获取获取不到

7.2、模块化开发

	由于企业开发项目一般都是有多人开发,一个html里可能会有十几个js文件,当这些js文件都被引入同一个html里时,就会出现很多问题,比如同名变量和方法,因为此时这些js都处于window全局对象里,所以当出现同名变量时,值就会发生变化。这时候就可以使用闭包来解决这种情况。
var initTest = (function (){
    var name,sex;
    function t1(){
        name ="ceshi"
    }
    function t2(){
        console.log(name)
    }
    return function(){
        t1()
        t2()
    }
}())
initTest()//这样不管谁开发的代码,只要直接调用这个方法名就可以了

八、DOM

九、事件

9.1、事件的绑定与移除

9.1.1.绑定

#html   onclick="在这里面写"

#on+type
ele.onxxx(function(){})

#addEventListener
obj.addEventListener(type,fn,boolean)  type:事件类型 fn 匿名函数/函数名 boolean true:捕获 false:冒泡

#IE attachEvent
obj.attachEvent('on'+type,fn)  //IE只有冒泡事件

9.1.2.解除

#on+type
ele.onxxx = null;

#addEventListener
obj.removeEventListener(type,fn,boolean)  type:事件类型 fn 匿名函数/函数名 boolean true:捕获 false:
解除时,fn必须是绑定的函数名,即使是相同的匿名函数也不行

#IE detachEvent
obj.detachEvent('on'+type,fn) 

9.2、事件模型

事件流:事件捕获阶段-->处于目标阶段-->事件冒泡阶段
前提:结构嵌套
先捕获在冒泡

9.2.1、捕获

父元素-->子元素
示例:当子元素触发点击事件时,会从父元素一层层向下,最后触发子元素的点击事件

9.2.2、冒泡

子元素-->父元素
示例:当子元素触发点击事件时,会一层层向上,触发父元素的点击事件

9.2.3、综合示例:

<div id="test1" style="width: 200px;height: 200px;background-color: red;">
    <div id="test2" style="width: 100px;height: 100px;background-color: blue;">
        <div id="test3" style="width: 50px;height: 50px;background-color: green;">

        </div>
    </div>
</div>
var div1 = document.getElementById('test1');
var div2 = document.getElementById('test2');
var div3 = document.getElementById('test3');

//捕获事件
div1.addEventListener('click',function(e){
    console.log("catch_111")
},true)
div2.addEventListener('click',function(e){
    console.log("catch_222")
},true)

div3.addEventListener('click',function(e){
    console.log("catch_333")
},true)


//冒泡事件
div1.addEventListener('click',function(e){
    console.log("doubble_111")
},false)
div2.addEventListener('click',function(e){
    console.log("doubble_222")
},false)
div3.addEventListener('click',function(e){
    console.log("doubble_333")
},false)

9.3、事件对象

其他:event
IE:window.event

事件源对象:原始操作元素对象,比如综合示例被点击的那个子元素
event.target 火狐
event.scrElement  IE
谷歌都有

9.4、事件委托

利用事件冒泡对事件源对象(可以理解为被点击的子元素)进行操作

--html
<ul id="ul">
    <li>1</li>
    <li>2</li>
    <li>3</li>
    <li>4</li>
    <li>5</li>
</ul>
--js
var ul = document.getElementById('ul');
ul.onclick = function(e){
    var event = e || window.event
    var target = event.target || event.srcElement
    console.log(target.innerText)
}

9.5、取消冒泡和阻止默认事件

9.5.1、取消冒泡

IE(9)
e.cancelBubble = true
非IE
event.stopPropagation()

方法封装(在当前点击的元素方法;里调用)
function stopDoubble(e){
    var event = e||window.event;
    if(event.stopPropagation{
        event.stopPropagation()
    }else{
        event.cancelBubble = false;
    }
}


--html
<div id="test1" style="width: 200px;height: 200px;background-color: red;">
    <div id="test2" style="width: 100px;height: 100px;background-color: blue;">
        <div id="test3" style="width: 50px;height: 50px;background-color: green;">

        </div>
    </div>
</div>
--js
var div1 = document.getElementById('test1');
var div2 = document.getElementById('test2');
var div3 = document.getElementById('test3');

// 冒泡事件
div1.addEventListener('click',function(e){
    console.log("doubble_111")
},false)
div2.addEventListener('click',function(e){
    console.log("doubble_222")
},false)
div3.addEventListener('click',function(e){
    stopDoubble(e)
    console.log("doubble_333")
},false)


function stopDoubble(e){
    var event = e||window.event;
    if(event.stopPropagation){
        event.stopPropagation()
    }else{
        event.cancelBubble = false;
    }
}

9.5.2、取消默认事件

默认事件:表单提交 a标签跳转 右键菜单等
IE(9)
e.returnValue = true
非IE
event.preventDefault()

方法封装
function preventDefaults(e){
    var event = e || window.event)
    if(event.preventDefault){
        event.preventDefault()
    }else{
        event.returnValue = false;
    }
}
--html
<a href="http://www.baidu.com" id="test1">火狐</a>
--js
var a = document.getElementById('test1');
a.onclick = function(e){
    preventDefaults(e)
    console.log('测试跳转')
}

function preventDefaults(e){
    // debugger
    var event = e || window.event
    if(event.preventDefault){
        event.preventDefault()
    }else{
        event.returnValue = false;
    }
}

9.6、事件类型

1.焦点事件

2.鼠标与滚轮事件

十、其他

10.1、对象枚举

for in
可枚举的
in 
属性是否可调用
instanceof
是否是一条链上的
hasOwnProperty
是否是自己定义的(原型上不算)

10.2、arguments.callee func.caller

arguments.callee 自己的引用
func.caller 谁调用func

10.3、克隆

//深度克隆
function deepClone(origin, target) {
    target = target || {};
    var	toStr = Object.prototype.toString;
    var	arrStr = "[object Array]";
    for (var prop in origin) {
        if (origin.hasOwnProperty(prop)) {
            if (origin[prop] !=='null' && typeof(origin[prop]) == 'object') {
                if (toStr.call(origin[prop]) == arrStr) {
                    target[prop] = [];
                } else {
                    target[prop] = {};
                }
                deepClone(origin[prop], target[prop]);
            } else {
                target[prop] = origin[prop];
            }
        }
    }
    return target
}

10.4、函数执行和创建对象的区别

function test(){
//this = object.create(test.prototype)
	a = 5;
	alert(a);
	alert(this.a);
	var a;
	alert(a)
}
test()
new test()
#解释:
test
AO{
	a:5
	this:window
}
new test()
AO{
	a:5,
	this:{}  //构造函数的this隐式赋值  看上面代码里注释 
}

加new操作符的变化,其实就只有this的指向发生改变

10.5、作用域

js没有块级作用域,所以不管是if还是for循环后面大括号里的变量都相当于在外面一层

if(true){
    var name = "ss";
}
相当于:
var name;
if(true){
    name = "ss";
}
函数外定义的变量拥有全局作用域

标签:function,ES5,console,log,对象,前端,JS,var,obj
From: https://www.cnblogs.com/simpletime/p/16768667.html

相关文章