本篇文章主要包含四大部分:基础总结、函数高级、对象高级、线程事件。
在下面2种情况下不加分号会有问题:
解决办法:在行首加分号!
除了上面两种情况,JS每一行是可以不加分号的!
基础总结部分包含:数据类型,变量,内存,对象,函数。
基本(值)类型:
Number -------- 任意数值
String -------- 任意字符串
Boolean -------- true/false
undefined -------- undefined
null -------- null
对象(引用)类型:
Object -------- 任意对象
Array -------- 一种特殊的对象(数组下标 内部数据有序)
Function -------- 一种特殊的对象(可以执行)
typeof:返回的是表示数据类型的字符串。
instanceof:用于检测构造函数的 prototype 属性是否出现在某个实例对象的原型链上。(在后续原型链的讲解上会深入探讨)
===:严格相等,即不仅值相等,还要类型相等。
“==”运算符会在进行相等比较之前先进行必要值的类型转换,先把值转换为一样的类型再进行相等比较。就算比较的值的类型不相同,也可以通过强制转换类型成一样的,不会发生错误。
而“===”运算符,它不会执行类型转换,因此如果两个值不是相同类型,那么当比较时,它将返回false。如果比较两个变量,它们的类型彼此不兼容,则会产生编译错误。
“===”运算符首先比较两边的变量数据类型是否相等,其次比较两边的变量的数值是否相等;只有数据类型和数值都相等了,两个变量才相等。
答:undefined代表定义未赋值;nulll定义并赋值了,只是值为null 。
答:初始赋值,表明将要赋值为对象;结束前,让对象成为垃圾对象(被垃圾回收器回收)。
答:数据类型包含基本类型和对象类型;变量类型其实是变量内存值的类型,即基本类型和引用类型,基本类型表示保存就是基本类型的数据,引用类型表示保存的是地址值。
什么是数据?
数据是在内存中可读的、可传递的、保存了特定信息的事物。
什么是变量?
变量是在程序运行过程中它的值是允许改变的量,其由变量名和变量值组成。
每个变量都对应的一块小内存,变量名用来查找对应的内存, 变量值就是内存中保存的数据。
什么是内存?
内存是内存条通电后产生的存储空间(临时的)。
内存产生和死亡:内存条(电路版)>>通电>>产生内存空间>>存储数据>>处理数据>>断电>>内存空间和数据都消失。
一块内存包含2个方面的数据:内部存储的数据,地址值数据。
内存,数据, 变量三者之间的关系?
内存是容器, 用来存储不同数据;变量是内存的标识, 通过变量我们可以操作(读/写)内存中的数据。
答:有以下几种情况:
xxx是基本数据,保存的就是这个数据。
xxx是对象,保存的就是对象的地址值。
xxx是一个变量,保存的就是xxx的内存内容( 可能是基本数据,也可能是地址值)。
答:有以下两种理解:
理解1:都是值(基本/地址值)传递;
理解2:可能是值传递, 也可能是引用传递(地址值);
答:内存的生命周期如下:
释放内存有以下两种情况:
一个对象代表现实中的一个事物。
统一管理多个数据。
属性组成:
属性的分类:
特别的对象:
① .属性名;
② ['属性名']: 属性名有特殊字符/属性名是一个变量;
①.属性名:编码简单,有时不能用;
②['属性名']:编码麻烦,能通用;
1.属性名包含特殊字符: - 空格
p['content-type'] ='text/json'
2.属性名不确定
var propName = 'myAge'
var value=18
p[propName] = vaLue
函数声明
function fn(){
}
表达式
var f=function fn(){}
注意函数也是对象:
1.test(): 直接调用;
2.obj.test():通过对象调用;
3.new test(): new调用;
4.test.call/apply(obj):临时让test 成为bj的方法进行调用;
我们首先要理解一个概念“类”,所谓类,指的是对象的模版,对象就是类的实例。
对象是单个实物的抽象,所以通常需要一个模版,表示某一类实物的共同特征,然后对象根据这个模版生成,这个过程就叫做对象实例化。
但是在JS中是没有“类”这个概念的,而是用构造函数来作为对象模版的,所谓构造函数,指的就是专门生成对象的函数。
什么函数才是回调函数?
常用的回调函数
1、this是什么?
任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window。
2、如何确定this的值?
函数高级部分包含:原型与原型链、执行上下文、执行上下文栈、变量提升、函数提升、作用域、作用域链、闭包。
首先,我们先区分三个概念,构造函数、实例对象、原型对象。
然后,我们再来回顾一个概念,函数也是对象,所以函数有属性和方法。
prototype
: 显式原型属性。__proto__
: 隐式原型属性。显式原型与隐式原型的关系:
函数的prototype: 定义函数时被自动赋值, 值默认为{}, 即用为原型对象。
相当于执行this.prototype={}
实例对象的__proto__: 在创建实例对象时被自动添加, 并赋值为构造函数的prototype值。
相当于执行this.__proto__=Fn.prototype
原型对象即为当前实例对象的父对象。
通过给原型对象添加属性( 一般都是方法),这样函数的所有实例对象自动拥有原型中的属性(方法)。
1、读取对象的属性值时:会自动到原型链中查找。
2、设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值。
3、方法一般定义在原型中,属性一般通过构造函数定义在对象本身上。
instanceof 是如何判断的?
1.变量声明提升?
2.函数声明提升?
先有变量提升,再有函数提升。
3.问题:变量提升和函数提升是如何产生的?
执行上下文与执行上下文栈:
分类:
生命周期:
包含哪些属性:
原型链是用来查找属性方法的!!
作用域链是用来查找变量的!!
查找一个变量的查找规则:
1、在当前作用域下的执行上下文中查找对应的属性,如果有直接返回, 否则进入2;
2、在上一级作用域的执行上下文中查找对应的属性,如果有直接返回, 否则进入3;
3、再次执行2的相同操作,.直到全局作用域, 如果还找不到就抛出找不到的异常;
注意:闭包存在于嵌套的内部函数中。
通过chrome工具得知: 闭包本质是内部函数中的一个对象, 这个对象中包含引用的变量属性。
当一个嵌套的内部(子)函数引用了嵌套的外部(父)函数的变量(函数)时,就产生了闭包。
产生闭包的个数 = 执行外部函数的次数。
1.产生:在嵌套内部函数定义执行完时就产生了(不是在调用)
2.死亡:在嵌套的内部函数成为拉圾对象时。
作用:
应用:
缺点:
1.内存溢出
2.内存泄露
常见的内存泄露:
对象高级部分包含:对象的多种创建模式、对象的继承模式。
var obj = {};
obj.name = 'Tom'
obj.setName = function(name){this.name=name}
var obj = {
name : 'Tom',
setName : function(name){this.name = name}
}
function Person(name, age) {
this.name = name;
this.age = age;
this.setName = function(name){this.name=name;};
}
new Person('tom', 12);
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.setName = function(name){this.name=name;};
new Person('tom', 12);
function Parent(){}
Parent.prototype.test = function(){};
function Child(){}
Child.prototype = new Parent(); // 子类型的原型指向父类型实例
Child.prototype.constructor = Child
var child = new Child(); //有test()
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){};
function Child(xxx,yyy){
Parent.call(this, xxx);//借用构造函数 this.Parent(xxx)
}
var child = new Child('a', 'b'); //child.xxx为'a', 但child没有test()
function Parent(xxx){this.xxx = xxx}
Parent.prototype.test = function(){};
function Child(xxx,yyy){
Parent.call(this, xxx);//借用构造函数 this.Parent(xxx)
}
Child.prototype = new Parent(); //得到test()
var child = new Child(); //child.xxx为'a', 也有test()
可以让js在分线程执行。
Worker。
var worker = new Worker('worker.js');
worker.onMessage = function(event){event.data} : 用来接收另一个线程发送过来的数据的回调
worker.postMessage(data1) : 向另一个线程发送数据
问题: