数据类型的分类和判断
1、分类
基本(值)类型
- String: 任意字符串
- Number: 任意的数字
- boolean: true/false
- undefined: undefined
- null: null
对象(引用)类型
- Object: 任意对象
- Function: 一种特别的对象(可以执行)
- Array: 一种特别的对象(数值下标, 内部数据是有序的)
2、判断
typeof:返回数据类型的字符串表达
- 可以判断: undefined/ 数值 / 字符串 / 布尔值 / function
- 不能判断: null与object object与array
instanceof:
- 判断对象的具体类型
===
- 可以判断: undefined, null
//1. 基本// typeof返回数据类型的字符串表达var aconsole.log(a, typeof a, typeof a==='undefined',a===undefined ) // undefined 'undefined' true trueconsole.log(undefined==='undefined') //flasea = 4console.log(typeof a==='number')a = 'atguigu'console.log(typeof a==='string')a = trueconsole.log(typeof a==='boolean')a = nullconsole.log(typeof a, a===null) // 'object'console.log('-----------------')//2. 对象var b1 = {b2: [1, 'abc', console.log],b3: function () {console.log('b3')return function () {return 'xfzhang'}}}console.log(b1 instanceof Object, b1 instanceof Array) // true falseconsole.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true trueconsole.log(b1.b3 instanceof Function, b1.b3 instanceof Object) // true trueconsole.log(typeof b1.b2, '-------') // 'object'console.log(typeof b1.b3==='function') // trueconsole.log(typeof b1.b2[2]==='function')b1.b2[2](4)console.log(b1.b3()())

常见问题
1、undefined与null的区别?
- undefined代表定义未赋值
- nulll定义并赋值了, 只是值为null
var aconsole.log(a) // undefineda = nullconsole.log(a) // null
2、什么时候给变量赋值为null呢?
- 初始赋值, 表明将要赋值为对象
- 结束前, 让对象成为垃圾对象(被垃圾回收器回收)
//起始var b = null // 初始赋值为null, 表明将要赋值为对象//确定对象就赋值b = ['atguigu', 12]//最后b = null // 让b指向的对象成为垃圾对象(被垃圾回收器回收)// b = 2
3、严格区别变量类型与数据类型?
数据的类型
- 基本类型
- 对象类型
变量的类型(变量内存值的类型)
- 基本类型: 保存就是基本类型的数据
- 引用类型: 保存的是地址值
数据,变量, 内存的理解
1、什么是数据?
- 存储在内存中代表特定信息的’东东’, 本质上是0101…
- 数据的特点: 可传递, 可运算
- 一切皆数据
内存中所有操作的目标: 数据
- 算术运算
- 逻辑运算
- 赋值
- 运行函数
2、什么是内存?
- 内存条通电后产生的可储存数据的空间(临时的)
- 内存产生和死亡: 内存条(电路版)>通电>产生内存空间==>存储数据==>处理数据==>断电==>内存空间和数据都消失
一块小内存的2个数据
- 内部存储的数据
- 地址值
内存分类
- 栈: 全局变量/局部变量
- 堆: 对象
3、什么是变量?
- 可变化的量, 由变量名和变量值组成
- 每个变量都对应的一块小内存, 变量名用来查找对应的内存, 变量值就是内存中保存的数据
4、内存,数据, 变量三者之间的关系
- 内存用来存储数据的空间
- 变量是内存的标识
常见问题
问题:var a = xxx, a内存中到底保存的是什么?
- xxx是基本数据, 保存的就是这个数据
- xxx是对象, 保存的是对象的地址值
- xxx是一个变量, 保存的xxx的内存内容(可能是基本数据, 也可能是地址值)
关于引用变量赋值问题
- 2个引用变量指向同一个对象, 通过一个变量修改对象内部数据, 另一个变量看到的是修改之后的数据
- 2个引用变量指向同一个对象, 让其中一个引用变量指向另一个对象, 另一引用变量依然指向前一个对象
<script type="text/javascript">var obj1 = {name: 'Tom'}var obj2 = obj1obj2.age = 12console.log(obj1.age) // 12function fn (obj) {obj.name = 'A'}fn(obj1)console.log(obj2.name) //Avar a = {age: 12}var b = aa = {name: 'BOB', age: 13} //这时候a指向另一个对象了,b仍然指向前一个对象,ab没有关系了b.age = 14console.log(b.age, a.name, a.age) // 14 Bob 13function fn2 (obj) {obj = {age: 15}}fn2(a)console.log(a.age) //是13不是15</script>
问题: 在js调用函数时传递变量参数时, 是值传递还是引用传递
- 理解1: 都是值(基本/地址值)传递
- 理解2: 可能是值传递, 也可能是引用传递(地址值)
问题: JS引擎如何管理内存?
- 内存生命周期
- 分配小内存空间, 得到它的使用权
- 存储数据, 可以反复进行操作
- 释放小内存空间
- 释放内存
- 局部变量: 函数执行完自动释放
- 对象: 成为垃圾对象==>垃圾回收器回收
<script type="text/javascript">var a = 3var obj = {}obj = undefinedfunction fn () {var b = {}}fn() // b是自动释放, b所指向的对象是在后面的某个时刻由垃圾回收器回收</script>
对象的理解和使用
1、什么是对象?
- 多个数据的封装体
- 用来保存多个数据的容器
- 一个对象代表现实中的一个事物
2、为什么要用对象?
- 统一管理多个数据
3、对象的组成
- 属性: 属性名(字符串)和属性值(任意)组成
- 方法: 一种特别的属性(属性值是函数)
<script type="text/javascript">var p = {name: 'Tom',age: 12,setName: function (name) {this.name = name},setAge: function (age) {this.age = age}}p.setName('Bob')p['setAge'](23)console.log(p.name, p['age'])/*p.setName输出的是一个函数,即function (name) {this.name = name}p.setName("bob")//加上括号之后就是调用函数*/</script>
4、如何访问对象内部数据?
.属性名:编码简单,有时不能用['属性名']:编码麻烦,能通用
问题1:什么时候必须使用['属性名']的方式?
- 属性名包含特殊字符:
-空格 - 属性名不确定,通过变量传递
<script type="text/javascript">var p = {}//1. 给p对象添加一个属性: content type: text/json// p.content-type = 'text/json' //不能用p['content-type'] = 'text/json'console.log(p['content-type'])//2. 变量名不确定var propName = 'myAge'var value = 18// p.propName = value //不能用p[propName] = valueconsole.log(p[propName])</script>
问题2:在js中用中括号访问对象的时候属性为什么要加上双引号?
首先声明一个对象 属性名加不加双引号都是可以的。
var obj = {name1: “张三”}
console.log(obj.name1) // 张三 用点语法 访问 没问题
console.log(obj[name1]) // 直接报 ReferenceError: name1 is not defined
不加双引号的话,js会认为这是变量名,而这个变量是不存在的,所以报“not defined”(未定义)的错误。
而这其实就是用中括号来访问对象属性的意义所在:可以用变量来代替属性名,比如:
var n = “name1”;
console.log(obj[n]); //obj[n]就相当于obj[“name1”]或obj.name1
而用点语法的话属性名是不能用变量的!
函数的理解和使用
函数的基本概念
1、什么是函数?
- 用来实现特定功能的, n条语句的封装体
- 只有函数类型的数据是可以执行的, 其它的都不可以
2、为什么要用函数?
- 提高复用性
- 便于阅读交流
3、函数也是对象
- instanceof Object===true
- 函数有属性: prototype
- 函数有方法: call()/apply()
- 可以添加新的属性/方法
函数的3种不同角色
- 一般函数 : 直接调用
- 构造函数 : 通过new调用
- 对象 : 通过.调用内部的属性/方法
、如何定义函数?
- 函数声明
- 表达式
function fn1() { //函数声明console.log('fn1()')}var fn2 = function () { //表达式console.log('fn2()')}
7、如何调用(执行)函数?
- test(): 直接调用
- obj.test(): 通过对象调用
- new test(): new调用
- test.call/apply(obj): 临时让test成为obj的方法进行调用
var obj = {}function test2() {this.xxx = 'atguigu'}// obj.test2() 不能直接, 根本就没有test2.call(obj) // obj.test2() // 可以让一个函数成为指定任意对象的方法进行调用console.log(obj.xxx) //输出'atguigu'console.log(obj.test2())//报错
回调函数的理解
什么函数才是回调函数?
- 你定义的
- 你没有调用
- 但它最终执行了(在一定条件下或某个时刻)
常用的回调函数
- dom事件回调函数
- 定时器回调函数
- ajax请求回调函数(后面讲解)
- 生命周期回调函数(后面讲解)
document.getElementById('btn').onclick = function () { // dom事件回调函数alert(this.innerHTML)}//定时器// 超时定时器// 循环定时器setTimeout(function () { // 定时器回调函数alert('到点了'+this)}, 2000)/*这两个方法我没有调用,但是他执行了*/
IIFE (Immediately Invoked Function Expression) 立即调用函数表达式
匿名函数自调用:
(function(w, obj){//实现代码})(window, obj)
作用
- 隐藏实现
- 不会污染外部(全局)命名空间
- 用它来编码js模块
(function () { //匿名函数自调用var a = 3console.log(a + 3)//6})()var a = 4console.log(a);//4
(function () {var a = 1function test2() {console.log(++a)}window.$ = function () { // 向外暴露一个全局函数return {//函数返回一个对象test: test2//test属性名,test2属性值}}})()$().test() // 1. $是一个函数 2. $执行后返回的是一个对象//
函数中的this
1、this是什么?
- 任何函数本质上都是通过某个对象来调用的,如果没有直接指定就是window
- 所有函数内部都有一个变量this
- 它的值是调用函数的当前对象
2、如何确定this的值?
- test(): window
- p.test(): p
- new test(): 新创建的对象
- p.call(obj): obj
3、
- 显式指定谁: obj.xxx()
- 通过call/apply指定谁调用: xxx.call(obj)
- 不指定谁调用: xxx() : window
- 回调函数: 看背后是通过谁来调用的: window/其它
function Person(color) {console.log(this)this.color = color;this.getColor = function () {console.log(this)return this.color;};this.setColor = function (color) {console.log(this)this.color = color;};}Person("red"); //this是谁? windowconsole.log(",,,,,")var p = new Person("yello"); //this是谁? Personp.getColor(); //this是谁? pvar obj = {};p.setColor.call(obj, "black"); //this是谁? objvar test = p.setColor;test(); //this是谁? windowconsole.log(",,,,,")function fun1() {function fun2() {console.log(this);}fun2(); //this是谁? window}console.log(",,,,,")fun1();
分号问题
js一条语句的后面可以不加分号
是否加分号是编码风格问题, 没有应该不应该,只有你自己喜欢不喜欢
在下面2种情况下不加分号会有问题
- 小括号开头的前一条语句
- 中方括号开头的前一条语句
强有力的例子: vue.js库
var a = 3;(function () {})()/*错误理解var a = 3(function () {})();*/var b = 4;[1, 3].forEach(function () {})/*错误理解var b = 4[3].forEach(function () {})*/
