01-严格模式
<script>
正常模式
num = 10;
console.log(num);
function fun(num, num) {
console.log(num + num);
}
fun(2, 3);
</script>
<script>
2.开启严格模式之后,函数的this指向,指向undefined
function fun1() {
flag = true;
console.log(flag);
console.log(this);
};
fun1();
为函数开启严格模式
function fun2() {
"use strict"
console.log(this);
flag = true;
console.log(flag);
};
fun2();
</script>
<script>
为脚本开启严格模式
1.不允许使用未声明的变量
"use strict";
str is not defined
str = '你好呀';
console.log(str);
function Person(name, age) {
this.name = name;
this.age = age;
};
var p1 = new Person('momoko', 20);
3.如果不用new ,构造函数的this指向undefined,所以会报错
var p1 = Person('张美丽', 20);
console.log(p1.name);
4.在严格模式下,定时器的this指向,指向window
setTimeout(function() {
console.log(this);
}, 1000);
5.不允许在此函数中不允许重复参数名称
function fun(num, num) {
console.log(num + num);
}
fun(2, 3);
</script>
<!-- 1.开启严格
脚本开启
函数内部开启
-->
<!-- 2.严格模式下的变化
不允许使用未声明的变量
开启严格模式之后,函数的this指向,指向undefined
实例化时如果不用new ,构造函数的this指向undefined,所以会报错
在严格模式下,定时器的this指向,仍然指向window
不允许在此函数中不允许重复参数名称
-->
02-高阶函数
符合条件其一:
- 参数是函数
- 函数作为返回值
1. 参数是函数
function superFun(arg) {
return arg + '超级帅';
};
function fun(str, callFun) {
console.log(callFun(str));
};
fun('杨正顺', superFun);
2.函数作为返回值
function fun(num) {
return function() {
console.log(num);
}
};
fun(100)();
03-变量的作用域
// 全局变量
var num1 = 10;
function fun() {
// 局部作用域
// 局部变量
var num2 = 100;
console.log(num2);
// 函数内部可以直接读取全局变量
console.log(num1);
};
fun();
// 函数外部无法读取函数内部的局部变量
console.log(num2);
04-闭包的定义
闭包:内部函数访问外部函数作用域的变量,形成的词法环境叫做闭包.
闭包的特点:
1.函数套函数
2.内部函数访问外部函数作用域的变量或参数
3.使局部变量长期贮存在内存中(延伸了局部变量的作用域)
闭包的坏处:有可能造成内存泄漏
内存泄漏:应用程序不再用到的内存,由于某些原因,没有及时释放,就叫做内存泄漏。
function fun1() {
var num = 10;
function fun2() {
console.log(num);
};
函数作为返回值
return fun2;
};
var rel = fun1();
可以打印出10
rel();
05-闭包的面试题1
function fun1() {
var num = 10;
// 函数作为返回值
return function() {
num++;
console.log(num);
}
};
// 作用:延伸变量的作用范围。
var rel = fun1();
rel();
rel();
rel();
rel();
06-闭包的面试题2
<style>
* {
margin: 0;
padding: 0;
}
ul {
list-style-type: none;
}
.list li {
width: 100px;
height: 100px;
border: 1px solid red;
float: left;
}
</style>
</head>
<body>
<ul class="list">
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
</ul>
<script>
// 获取索引位
// 获取是伪数组
// js单线程
var lis = document.getElementsByTagName('li');
for (var i = 0; i < lis.length; i++) {
(function(t) {
lis[t].onclick = function() {
console.log(t);
};
})(i)
};
</script>
07-递归函数
递归函数:在函数内部自己调用自己
注意退出条件
求1~n的阶乘
1*2*3*4*....n-1*n
function factorial(n) {
if (n == 1) {
return 1;
}
return n * factorial(n - 1);
};
console.log(factorial(4));
n=4
24
4 * factorial(3)
4 * 3 * factorial(2)
4 * 3 * 2 * 1
08-抚平数组
// 抚平数组
// 将多维数组转换为一维数组的过程称为抚平数组
function flatArrFun(arr, relArr) {
if (!Array.isArray(arr)) {
return arr;
};
// 设定参数的初始值
relArr = relArr || [];
for (var i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
console.log(arr[i]);
flatArrFun(arr[i], relArr)
} else {
relArr.push(arr[i]);
};
}
return relArr;
};
var arr = [1, 2, 3, [4, 5, [6, 7, 8]]];
// 得到结果是:[1,2,3,4,5,6,7,8]
console.log(flatArrFun(arr));
09-地址传递
<script>
var obj1 = {
name: '张美丽',
hobby: ['运动', '敲代码', '谈恋爱']
};
var obj2 = {
name: '张美丽',
hobby: ['运动', '敲代码', '谈恋爱']
};
// 赋值--地址传递
var obj3 = obj1;
console.log(obj1 == obj2); //false
console.log(obj1 == obj3); //true
</script>
10-浅拷贝
// 浅拷贝:拷贝出来的目标对象的复杂数据类型的地址和源对象的复杂数据类型的地址的内存空间是同一块空间,修改其中一个对象,另外一个对象将会受到影响
var obj = {
name: '张美丽',
age: 20,
hobby: ['运动', '敲代码', '谈恋爱']
};
// 1.for..in进行浅拷贝
var copyObj = {};
// for (var key in obj) {
// copyObj[key] = obj[key];
// };
// copyObj.hobby[1] = '挣钱';
// console.log(copyObj);
// console.log(obj);
// 2.Object.assign(target, ...sources):实现对对象的浅拷贝
Object.assign(copyObj, obj);
copyObj.hobby[1] = '挣钱';
console.log(copyObj);
console.log(obj);
11-递归实现深拷贝
// 深拷贝:拷贝出来的目标对象的和原目标对象,相互之间互不影响.修改其中一个对象,两外一个对象不会进行影响
var obj = {
name: '张美丽',
age: 20,
hobby: ['运动', '敲代码', '谈恋爱'],
school: {
id: 'y001',
sname: '姚班'
}
};
var copyObj = {};
// 1.for..in进行深拷贝
function deepCopy(newObj, oldObj) {
for (var key in oldObj) {
// 1.获取对象的每项属性或方法的值
var item = oldObj[key];
if (item instanceof Array) {
// 2.如果是复杂数据类型,就遍历进行一个个赋值
newObj[key] = [];
deepCopy(newObj[key], item);
} else if (item instanceof Object) {
newObj[key] = {};
console.log(item);
deepCopy(newObj[key], item);
} else {
newObj[key] = item;
}
}
};
deepCopy(copyObj, obj);
// 修改拷贝后的对象
copyObj.hobby[0] = '读书';
copyObj.school.id = 'y002';
console.log(copyObj);
console.log(obj);
12-使用JSON实现深拷贝
// 深拷贝:拷贝出来的目标对象的和原目标对象,相互之间互不影响.修改其中一个对象,两外一个对象不会进行影响
var obj = {
name: '张美丽',
age: 20,
hobby: ['运动', '敲代码', '谈恋爱'],
school: {
id: 'y001',
sname: '姚班'
},
sayHi: function() {
console.log('函数');
},
rp: /abc/
};
var copyObj = {};
// JSON.stringify(obj):将对象转换成JSON字符串
console.log(JSON.stringify(obj));
// JSON.parse(str):将JSON字符串转换为对象
console.log(JSON.parse('{"name":"张美丽","age":20,"hobby":["运动","敲代码","谈恋爱"],"school":{"id":"y001","sname":"姚班"}}'));
// 进行深拷贝
copyObj = JSON.parse(JSON.stringify(obj));
// 修改拷贝后的对象
// copyObj.hobby[0] = '读书';
// copyObj.school.id = 'y002';
console.log(copyObj);
console.log(obj);
// 缺点:对个别复杂数据类型没办法友好的拷贝
点赞作业-1
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>对自己狠点</title>
<style>
ul {
list-style-type: none;
}
li {
float: left;
margin-left: 10px;
}
img {
width: 180px;
height: 180px;
}
input {
margin-left: 30%;
}
</style>
</head>
<body>
<ul>
<li><img src="img/xs.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
<li><img src="img/dc.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
<li><img src="img/wzj.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
<li><img src="img/yyh.jpg" alt=""><br/><input type="button" value="赞(1)"></li>
</ul>
<script>
//获取所有的按钮
//根据标签名字获取元素
function my$(tagName) {
return document.getElementsByTagName(tagName);
}
//闭包缓存数据
function getValue() {
var value=2;
return function () {
//每一次点击的时候,都应该改变当前点击按钮的value值
this.value="赞("+(value++)+")";
}
}
//获取所有的按钮
var btnObjs=my$("input");
//循环遍历每个按钮,注册点击事件
for(var i=0;i<btnObjs.length;i++){
//注册事件
btnObjs[i].onclick=getValue();
}
</script>
</body>
</html>
作业2,3,4
2.
setTimeout(func(parma), 1000);
function func(num) {
console.log(num);
};
参数使用字符串
setTimeout('func(200)', 1000);
3.执行代码顺序
console.log('start');
setTimeout(function() {
console.log('你猜我输出在哪2000');
}, 2000);
setTimeout(function() {
console.log('你猜我输出在哪1000');
}, 1000);
console.log('end');
for (var i = 0; i < 10; i++) {
console.log(i);
}
console.log('start');
for (var i = 0; i < 3; i++) {
(function(index) {
setTimeout(function() {
console.log(index);
}, 0);
})(i);
}
console.log('end');
4.斐波那契
//斐波拉契题(兔子生兔子题目)--从出生后第3个月起每个月都生一对兔子,小兔子长到第三个月后
每个月又生一对兔子,假如兔子都不死,问每个月的兔子对数为多少
// 产量分析:1, 1, 2, 3, 5, 8, 13, 21 。。。
//及前个数相加等于第三个数1+1=2,1+2=3,2+3=5。。。。
// 第n个月的兔子总数 = 第n-1个月的兔子总数 + 第n-2个月的兔子总数
// 问题: 求任意月兔子的总数
function func( n )
{
if (n == 0 || n == 1)
{
return 1;
}
return func(n-1) + func(n-2);
}
var a = func(22);
console.log(a);