学习链接:视频https://www.bilibili.com/video/BV14s411E7qf?p=1
MDN:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
一、基础总结
1、数据类型
1.1数据类型分类
基本(值)数据类型(五种)
String:任意字符串
Number:任意数字
Boolean:true/false
null:null
undefined:undefined对象(引用)数据类型
Object:任意对象都是Object(object是通过构造函数来进行表达的)
Function:一种特别的对象(用来存储可以执行的代码)
Array:一种特别的对象(数值下标,内部数据是有序的)
Date:日期对象
RegExp:正则表达式
1.2数据类型判断
- typeof:返回数据类型的字符串表达,可以判断String | Number | Boolean | undefind | function 的数据类型;不能判断null与object,object与array
var a
console.log(typeof a) //打印出来的值为字符串 'undefined'
console.log(typeof a === undefined) //false
console.log(typeof a === 'undefined') //true
console.log(a === undefined) //true
// -----注意:typeof无法判断null的类型-----
var b = null
console.log(typeof b) //控制台打印出来的结果为'object'
// -----注意:typeof无法判断Array的类型-----
var A = []
console.log(typeof A) //控制台打印出来的结果为'object'
// -----注意:typeof可以判断对象Function-----
var f = function () { console.log ('sss') }
console.log(typeof f) //控制台打印出来的结果为'function'
- instanceof:判断对象的具体类型,返回一个布尔值
var c = {
c1: [1, 'sbc', console.log],
c2: function () {
console.log('c3')
},
c3: function () {
return function () {
return 'x-man'
}
}
}
// -------
console.log(c instanceof Object, c instanceof Array) //true,false
console.log(c.c1 instanceof Object, c.c1 instanceof Array) //true,true
console.log(c.c2 instanceof Object, c.c2 instanceof Function) //true,true
console.log(typeof c.c2 === 'function') //true
// 注意 c.c1[2]是一个函数,可以直接调用
console.log(typeof c.c1[2]) //'function'
c.c1[2]( '这是一个log函数,可直接使用' )// 控制台将会输出这个字符串
console.log( c.c3()() ) // 控制台输出字符串 'x-man'
- ===:判断是否全等。可以判断null和undefind类型
1.3相关问题
null和undefined有什么区别
undefined代表定义未赋值,null代表定义并赋值了,只是赋值为null什么时候给变量赋值null
情况一:初始赋值为null,表明将要赋值为对象;
情况二:让对象成为垃圾对象(被浏览器垃圾回收器回收)。严格区别变量类型与数据类型
数据类型:基本类型和对象类型
变量数据类型:基本数据类型(变量保存的是基本类型的数据)、引用类型(保存的是地址值)
2、数据、变量与内存
2.1基本概念
- 数据:存储在内存中的代表特定信息的东西,本质上是二进制信息
数据的特点:可传递、可运算、 - 变量:可变化的量,由变量名和值组成。变量名对应内存地址,值为内存中保存的数据
- 内存:临时的数据存储空间。一块小内存有两个数据(内存内部存储的数据和它本身的地址数据)
- 内存的分类:
栈:存储全局变量和局部变量
堆:存储对象
2.2数据、变量与内存三者之间的关系
内存是用来存储数据的临时空间 ,变量是内存的标识,
2.3相关问题
- 关于引用变量赋值问题
多个引用变量指向同一个对象,当其中的某一个引用变量改变对象内的属性,其他引用变量也会发生改变。 - 关于数据传递问题:js调用函数传递变量参数时,是值传递还是引用传递
理解一:都是值(基本/地址值)传递
理解二:可能是值传递也可能是引用传递(地址值) - JS引擎如何管理内存
< 1 >内存生命周期:分配小内存空间,得到使用权==》存储数据(可以进行反复操作)== 》释放小内存空间
< 2 >释放内存:
局部变量:函数执行完自动释放
对象:先成为垃圾对象,再由垃圾回收器回收
3、对象
3.1什么是对象,为什么要用对象
对象是多个数据的封装体,是用来保存多个数据的容器。对象可以同意管理多个数据。
3.2对象的组成
属性名(字符串)和属性值(任意)组成
3.3如何访问对象内部数据
方法一:对象.属性名
编码简单,但是有时不能用。比如属性名包含空格、-
方法二:对象[ ' 属性名' ]
编码麻烦,但是通用。属性名不确定的情况下可以使用这种方式;属性名包含特殊字符空格、-
// 1、属性名包含空格或者-
var p ={}
p['content-type'] = 'text/json'
// 2、变量名不确定
var propAge = 'JarvisAge'
var value = 18
p[propAge ] = value //相当于p[JarvisAge] = 18
4、函数
4.1什么是函数,为什么要用函数,如何定义函数
函数是代码封装体。提高代码复用。
- 函数声明的方式:
function fn1 () {
console.log('sss')
}
- 表达式的方式:
var fn2 = function () {
console.log('sss')
}
4.2如何调用(执行)函数
test()
obj.test()
new test()
test.call( obj ) / apply( obj );可以让一个函数成为指定任意对象的方法进行调用。
4.3回调函数
什么函数是回调函数
定义的函数没有调用,但是它自身执行了。常见的回调函数
< 1 >DOM事件回调函数
< 2 >定时器回调函数
< 3 >ajax请求回调函数
< 4 >生命周期回调函数
5、IIFE(immediately-invoked function expression)
作用:隐藏实现,不会污染全局命名空间。可以用来编写js模块
(function () { // 匿名函数自调用
var a = 10
console.log(a)
})()
// ----
(function () {
var a = 1
function test () {
console.log(++a)
}
window.$ = function () { // 向外暴露一个全局函数
return {
test: test
}
}
})()
$().test() // 控制台输出2
6、this
this是什么?
所有函数内部都有的一个变量this,它的值是调用函数的当前对象如何确定this的值
任何函数本质上都是通过某个对象来调用的,如果没有指定对象调用,this就是window。
二、函数高级
1、原型与原型链
1.1原型(prototype)
- 每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为原型对象)
原型对象中都有一个constructor属性,它默认指向函数对象
console.log(Date.prototype,typeof Date.prototype) // 控制台输出Date中的属性,object
// constructor属性
function Fun () {}
console.log(Fun.prototype) // 默认指向一个object空对象(没有属性)
console.log(Fun.prototype.constructor === Fun) //输出true,constructor属性,它默认指向函数对象
- prototype作用:给原型对象添加属性(一般是添加方法)。函数的所有实例对象自动拥有原型中的属性(方法)
function Fun () {}
Fun.prototype.test = function () {
console.log('sss')
}
// 实例化对象
var fun = new Fun()
fun.test() // 使用原型中的test方法,控制台输出sss
1.2显式原型与隐式原型
每个函数都有一个prototype,即显式原型(属性)
每个实例对象都有一个_ proto _,即隐式原型(属性)
注意:prototype和__proto__都是引用变量,保存原型对象的地址值,所以两个变量都是指向原型对象的
实例对象的隐式原型的值为其对应构造函数的显式原型的值
function Fun () {} // 内部语句:this.prototype = {}
var fun = new Fun() // 内部语句:this.__proto__ = Fun.prototype
console.log(Fun.prototype)
console.log(fun.__proto__)
console.log(fun.__proto__ === Fun.prototype)
内存结构图:
总结:
函数的prototype属性:在定义函数时自动添加的,默认值是一个空的Object对象。
实例对象的 _ proto _ 属性:在创建实例对象时自动添加的,默认值为构造函数的prototype属性值。
1.3原型链(隐式原型链)
访问一个对象属性时:先在自身属性中查找,找到返回出去;如果没有找到,再沿着_ proto _这条链向上查找,找到返回出去;如果最终没有找到,则返回undefined。
1.4探索instanceof
- 函数的显式原型指向的对象默认是空Object实例对象(但是Object函数不满足)
console.log(Fun.prototype instanceof Object) // true
console.log(Object.prototype instanceof Object) // false
console.log(Function.prototype instanceof Object) // true
- 所有函数都是Function的实例(包括Function本身)
console.log(Function.__proto__ === Function.prototype) // true
- Object的原型对象是原型链的尽头
console.log(Object.prototype.__proto__) // null
2、执行上下文与执行上下文栈
2.1变量提升与函数提升
- 变量声明提升:通过var定义(声明)的变量,在定义语句之前就可以访问到
- 函数声明提升:通过function声明的函数,在之前就可以直接调用
2.2执行上下文
2.2.1全局执行上下文
第一步:在全局执行代码前将window确定为全局执行上下文
第二部:对全局数据进行预处理:
- var定义的全局变量(值为undefined)添加为window的属性;
- function声明的全局函数(赋值fun)添加为window的方法;
- this指向window
第三步:开始执行全局代码
console.log(a1,window.a1) // a1的值为undefined
a2()
console.log(this)
var a1 = 2;
function a2 () {
console.log('a2()')
}
2.2.2函数执行上下文
第一步:在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)
第二部:对局部数据进行预处理
- 对形参变量进行赋值(实参),添加为执行上下文的属性;
- arguments (实参列表),添加为执行上下文的属性;
- var定义的局部变量(赋值为undefined),添加为执行上下文的属性;
- function声明的函数(赋值为fun),添加为执行上下文的方法;
- this指向调用函数的对象
第三步:开始执行函数体代码
function fn (item) {
console.log(item) // 2
console.log(a1) // undefined
a2() // a2()
console.log(this) // window
console.log(arguments) // 伪数组(2, 3)
var a1 = 2
function a2 () {
console.log('a2()')
}
}
fn(2, 3)