JS 笔记
1.什么是数据
存储再内存中代表特定信息的 ‘东东’ ,本质上是0101…
数据的特点:可传递,可运算
一切皆数据
内存中所有操作的目标:数据
算数运算
逻辑运算
赋值
运行函数
2.什么是内存
1、内存条通电后产生的可存储数据的空间(临时的)
2、内存的产生和死亡:内存条(电路板): 通电 ==》 产生内存空间 ==》 存储数据 ==》 处理数据 ==》断电 ==》内存空间和数据都消失
3、一块小内存的两个数据
内部存储的数据
地址值
var obj = {name: ‘tom’};
这句话 中,先创建存储空间 自动匹配一个 地址 ,然后 开辟空间存储 name: ‘Tom’, 将 地址 赋值给 obj, obj 这个地址 指向的 就是后面 的 内容。
4、内存的分类
栈:全局变量|局部变量
堆:
3.什么是变量
1.可变化的量,由变量名和变量值组成
2.每个变量都对应一块小内存,变量名用户来查找对应的内存,变量值就是内存中保存的数据
4.三者之间的关系
1.内存是用来存储数据的空间(临时空间,硬盘才是永久空间)
2.变量是是内存的标识
Q:
var a = xxx ,a内存中到底保存的是什么?
-xxx 如果是基本数据,保存的就是这个数据
-xxx 是对象的话,保存的就是这个对象的地址值
-xxx 是一个变量,内存里保存的是,xxx 的内存内容(可能是基本数据,也可能是地址值)
var obj1 ={name:'tom}
var obj2 = obj1
这里是将, obj1 的内容 赋值给了 obj2 , 但是赋值的内容就是 ‘地址值’,所以 obj2 的内容就是 {name:‘tom’} 内存的地址值
所以他们指向的都是一个 地址 ,意思是他们都是标识的一个 对象 ,于是 通过 obj1,obj2 更改后,另一个都会实时改变。
5.JS引擎如何管理内存
1.内存生命周期
- 分配小内存空间,得到他的使用权
- 存储数据,可以反复操作使用
- 释放小内存空间
2.释放内存
- 局部变量:函数执行完自动释放
- 对象:先成为 垃圾对象 ==》 垃圾回收器回收
6.对象
1.什么是对象
- 多个数据的封装体(一个数据只能存储一个数据 ,对象可以存储 多个数据)
- 用来保存多个数据的容器
- 一个对象代表现实中的一个事物
2.为什么要用对象
- 统一管理多个数据
3.对象的组成
- 属性: 属性名(字符串) , 和属性值(任意类型)组成
- 方法 :一种特殊的属性(属性值是函数)
4.如何访问对象内部数据
- . 属性名(obj.name)有时不能用 : p.consten-type = ‘text-json’ 含有特殊字符 - 空格之类的无法赋值
- [‘属性名’] , 一直都能用 : p[‘content-type’] = ‘text-json’ 可以使用
- p.propName = value (用不了,因为变量名是不确定的无法使用) p[propName] = value 就可以使用
7.函数
1.什么是函数?
- 实现特定功能的多条语句的封装体
- 只有函数是可以执行的,其他类型的数据无法执行
2.为什么要用函数?
- 提高代码复用
- 便于阅读交流
3.如何定义函数?
- 函数声明: function fun1() { }
- 表达式: var fun2 = function () { }
这里要注意 :
- 函数声明方式 会 函数提升,可以在后面声明,前面调用
- 函数表达式,没有函数提升,只能在前面定义,后面调用
4.如何调用(执行)函数?
- test(): 直接调用
- obj.test() : 通过对象调用
- new test(): new 调用
- test.call/apply(obj): 临时让 test 方法,成为obj 的方法来调用
5.回调函数
- 定义: 你定义了 ,但是没有自己调用 ,但是它最终执行了
- 常见的回调函数:
- DOM事件回调函数(点击事件 onclick onmousemove 这类,是触发时自己就调用了)
- 定时器回调函数: setTimeout(function(){} , 3000),两个参数, 到了一定时间后,自动调用的函数,这也是自己定义但是自己没有主动调用的函数
- ajax 请求回调函数
- 生命周期回调函数
- DOM事件回调函数(点击事件 onclick onmousemove 这类,是触发时自己就调用了)
6.IIFE(立即执行函数表达式)
- 全称: 立即执行函数表达式
- 表示: ( function (){conslos.log('匿名函数喔')}) ()
- 作用:
- 隐蔽实现
- 不会污染外部空间(全局)命名空间
- 编写 JS 模块
- 隐蔽实现
7.函数中的 this
- this是是什么
- 任何函数本质上都是通过某个对象来调用的 , 如果没有指定就是 window
- 所有函数内部都有一个变量this
- 它的值是调用函数的当前对象
- 任何函数本质上都是通过某个对象来调用的 , 如果没有指定就是 window
- 如何确定this 的值
- 见代码
8.函数高级
1.原型与原型链
原型有两种: 显示原型 prototype ,隐式原型 // __proto,.
<script type="text/javascript">
// 每个函数都有一个 prototype 属性,在默认指向一个 Object 空对象(为: 原型对象)
console.log(Date.prototype);
function fun(){
}
console.log(fun.prototype); // 默认指向一个 Object 空对象(没有我们的属性)含有两个对象 constructor prototype
// 原型对象中有一个属性,constructor,他指向函数对象
console.log(Date.prototype.constructor === Date); // ==> true
console.log(fun.prototype.constructor === fun); // ==> true
// 给原型添加属性(一般是方法),===> 实例对象都可以访问
fun.prototype.test = function (){
console.log('test!!!');
}
var a = new fun();
a.test(); // 输出 test!!!
</script>
** 显示原型与隐式原型的关系
<script type="text/javascript">
/*
* 每个函数 function 都有一个 prototype ,即 显示原型(属性)
* 每个实例对象都有一个 __proto__,可称为隐式原型(属性)
* 对象的隐式原型的值为其对应的构造函数的显示原型的值
* 内存构造
* 总结;
* - 函数的prototype属性,在 定义函数时 自动添加的,默认值是一个空的 Object对象
* - 对象的__proto__属性,创建对象时 自动添加的,默认值为构造函数的prototype属性值
* - 程序员能直接操作显示原型,但是不能直接擦做隐式原型(ES6之前)(操作显示,隐式自动会变,因为显隐指向同一块对象)
* */
function Fn(){
}
// 1. 每个函数 function 都有一个 prototype,即 显示原型
// ** 函数也是可以使用 Fn.__proto__.__protp__ 的 返回的是个对象
// 使用 Fn.__proto__ 返回的是个 Function 是个函数
console.log(Fn.prototype); // ===> object{}
console.log(Fn.__proto__); // ===> function()
// 2. 每个实例对象都有一个 __proto__ ,可称为隐式原型
var fn = new Fn()
console.log(fn.prototype); // ===> undefined
console.log(fn.__proto__); // ===> object{}
// 3.对象的隐式原型的值 就是 其对应显示原型的值 ===
console.log(Fn.prototype === fn.__proto__); // ===> true
/*
* 函数的prototype属性,在 定义函数时 自动添加的,默认值是一个空的 Object对象
* 对象的__proto__属性,创建对象时 自动添加的,默认值为构造函数的prototype属性值
* */
function Fn() {} // 内部语句: this.prototype = {} 等于一个空对象
var fun = new Fn() // 内部语句: this.__proto__ = Fn.prototype (相当于是把 Fn 的原型的地址赋值给了 fn 的 __proto__)
</script>
** 原型链 (也叫做隐式原型链,因为是根据 隐式原型__proto__,一层一层往里找的 )
- 作用: 查找对象的属性
构造函数的显示原型 是 实例对象的隐式原型
原型继承:
- 构造函数的实例对象自动拥有构造函数原型对象的属性(方法)
- 利用的就是原型链
补充:
-
函数的显示原型指向的对象是默认是空 Object 实例对象(只有Object自己不满足)
-
console.log(Fn.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
-
9.闭包:
<script type="text/javascript">
/* function fn1(){
var a = 2;
return function (){
console.log(a);
}
}
var test = fn1();
console.log(fn1().a);;*/
/*for (let i = 0 ; i<5 ; i++){
var a = 3;
console.log('这是循环里面的i :' , i);
console.log('a = ', a);
}
// console.log('这是循环外面的i : ', i);
console.log(a);
function test(){
var x = 6;
console.log('这是函数内部的x: ', x);
}
test();
console.log('这是外部的 x: ', x);*/
/*var name = 1;
var obj = {
name: 2,
getName: function (){
var that = this; // 把当前的 this ,指向的对象 obj ,保存到 that 中。所以在下面调用的时候,就还会返回 obj 内的对象
return function (){
alert(name)
}
}
};
// alert(obj.getName()());
window.obj.getName()();*/
/*
* 定义一个函数,外界只能操作他+1
* */
/*function countAdd(){
var a = 0;
function fn (){
a++;
alert(a)
}
return fn;
}
var fun = countAdd();
fun();*/
/*
* 制作一个 计时器,每隔一秒钟加一
* */
/*// 先定义一个 秒数
var second = 0;
// 先定义一个 秒数
var second = 0;
// 定义一个加时器
function addSecond(){
second++;
// 添加一个判断,让他 10s 的时候就停止
if (second >= 10){
console.log('计时器停止了!!');
clearInterval(timer);
return;
}
console.log(second);
}
// 定义一个定时器,调用加时函数
var timer = setInterval(addSecond , 1000);
</script>
闭包的应用:定义 JS 模块
- 具有特定功能的 JS 文件
- 将所有的数据和功能都封装到一个函数内部(私有的)
- 只向外暴露一个 包括 n 个方法的对象或者函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
定义一个js文件,myModule.js,在内部编写函数,接着在一个 HTML文件中引用
function myModule(){
// 函数内部的私有属性
var msg = 'Liumingjie'
function Big(){
console.log('Big函数: ' + msg.toUpperCase());
}
function Little(){
console.log('Little函数: ' + msg.toLowerCase());
}
// return Big; //返回这一个函数
return {
Big: Big,
Little: Little
}
}
(function myModule2 (){
var msg = 'Liumingjie'
function Big(){
console.log('Big函数: ' + msg.toUpperCase());
}
function Little(){
console.log('Little函数: ' + msg.toLowerCase());
}
window.myModule2 = {
Big: Big,
Little: Little
}
}
)()
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>闭包的应用</title>
</head>
<body>
<!--
闭包的应用:定义 JS 模块
- 具有特定功能的 JS 文件
- 将所有的数据和功能都封装到一个函数内部(私有的)
- 只向外暴露一个 包括 n 个方法的对象或者函数
- 模块的使用者,只需要通过模块暴露的对象调用方法来实现对应的功能
-->
<script type="text/javascript" src="JS/myModule.js"></script>
<script type="text/javascript">
// 这种情况的时候,可以直接再 window 中找到
myModule2.Big(); // Big函数: LIUMINGJIE
myModule2.Little(); // Little函数: liumingjie
// 需要执行函数后,引用他才能得到
var fn = myModule();
fn.Big(); // Big函数: LIUMINGJIE
fn.Little(); // Little函数: liumingjie
// 最后不管是定时器还是闭包函数都要清除
fn = null;
</script>
</body>
</html>
闭包面试题目:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>闭包面试题</title>
</head>
<body>
<script type="text/javascript">
var name = 'This Window';
var Object = {
name: 'My Object',
getName: function (){
return function (){
return this.name
}
}
}
alert(Object.getName()()); // This window
// 首先要清楚最后的结构是什么 相当于下面这个
// var fun1 = Object.getName();
// alert(fun1());
// 很明显可以看到Object.getName() 是获得的一个函数名字,最后加括号才是完成函数的调用,而 fun1(),这函数调用的对象是 window.fun1();
var name2 = 'This Window'
var Object2 = {
name2: 'My Object',
getName2: function (){
var that = this
return function (){
return that.name2
}
}
}
alert(Object2.getName2()()) // My Object
// 这里相当于,把当时的 this 指向的对象,赋值给了 that 所以,就算是 window调用这个函数,他也是指向的 Object
</script>
</body>
</html>