第一章、类和对象
- 创建类和对象
<script>
// 1.创建类 class 创建一个明星类
class Star {
// constructor 接受类的公共属性 ,也是构造函数(构造器)
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
// 公共的方法
sing(song) {
console.log(this.uname + song);
}
}
// 2.利用类创建对象 new
let ldh = new Star('刘德华', 48);
let zxy = new Star('张学友', 48);
console.log(ldh);
console.log(zxy);
ldh.sing('冰雨');
zxy.sing('李香兰');
//(1)通过class关键字创建类,类名我们还是习惯性定义首字母大写
//(2)类里面有个constructor函数,可以接受传递过来的参数,同时返回实例对象
//(3) constructor 函数只要new 生成实例时,就会自动调用这个函数,如果我们不写这个函数,类
//也会自动生成这个函数
//(4) 生成实例new不能省略
//(5)最后注意语法规范,创建类类名后面不要加小括号,生成实例类名后面加小括号,构造函数不需
//要加function
</script>
- 类的继承
<script>
// 1.类的继承
/* class Father {
constructor() {
}
money() {
console.log(100);
}
}
class Son extends Father {
}
let son = new Son();
son.money(); */
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
class Son extends Father {
constructor(x, y) {
super(x, y);//调用父类里面的方法
}
}
let son = new Son(2, 6);
son.sum();
- 使用super关键字调用父类普通函数
<script>
// super 关键字调用父类的普通函数
class Father {
say() {
return '我是爸爸';
}
}
class Son extends Father {
say() {
console.log(super.say() + '的儿子');
// super.say() 就是调用父类中的普通函数 say()
}
}
let son = new Son();
son.say();
// 继承中的属性或者方法查找原则:就近原则
// 1.继承中, 如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
// 2.继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
</script>
- 子类继承父类的方法同时扩张自己的方法
<script>
class Father {
constructor(x, y) {
this.x = x;
this.y = y;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类的方法 同时添加自己的方法
class Son extends Father {
constructor(x, y) {
// 子类在构造函数中使用super必须放到this前面 (先调用父类的构造器方法,在使用子类的构造器方法)
super(x, y);
this.x = x;
this.y = y;
}
subtract() {
console.log(this.x - this.y);
}
}
let son = new Son(10, 5);
son.subtract();
son.sum();
</script>
- 使用类的注意事项
<script>
class Star {
// constructor 里面的this指向的是 创建的实例对象
constructor(uname, age) {
this.uname = uname;
this.age = age;
// 调用实例化类的方法 用this.方法
this.sing();
}
// sing里面的this指向的是调用者
sing() {
console.log(this.uname);
}
}
let ldh = new Star('刘德华');
// 1.在es6中类没有变量提升,所以必须先定义类,才能通过类实例化对象
// 2.类里面的共有的属性和方法一定要加this使用
// 总结:constructor里面的this指向的的实例对象 方法里面的this指向的是这个方法的调用者
</script>
- es6类的本质
<script>
// ES6之前通过构造函数+原型实现面向对象编程
// (1) 构造函数有原型对象prototype
// (2)构造函数原型对象prototype 里面有constructor 指向构造函数本身
// (3)构造函数可以通过原型对象添加方法
// (4) 构造函数创建的实例对象有_ proto_ 原型指向构造函数的原型对象
//ES6通过类实现面向对象编程
class Star {
}
// 1.类的本质其实也是一个函数 ,我们也可以简单的认为 类就是 构造函数的另外一种写法
console.log(typeof Star);
// (1).类有原型对象prototype
console.log(Star.prototype);
// (2). 类原型对象prototype 里面有constructor 指向的是类本身
console.log(Star.prototype.constructor);
// (3).类可以通过原型对象添加方法
Star.prototype.sing = function () {
console.log('冰雨');
}
var ldh = new Star();
console.dir(ldh);
// 类创建的实例对象,有__proto__原型指向类的原型对象
console.log(ldh.__proto__ === Star.prototype);
</script>
第二章、构造函数创建对象
- 利用构造函数创建对象
<script>
// 3.利用构造函数创建对象
function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function () {
console.log('我会唱歌');
}
}
let ldh = new Star('刘德华', 35);
let zxy = new Star('张学友', 35);
console.log(ldh);
ldh.sing();
zxy.sing();
</script>
- 构造函数的静态成员和实例成员
<script>
// 3.利用构造函数创建对象
function Star(uname, age) {
this.uname = uname;
this.age = age;
this.sing = function () {
console.log('我会唱歌');
}
}
let ldh = new Star('刘德华', 35);
// 1.实例成员就是构造函数内部通过this添加的成员 uname age sing 就是实例成员
// 实例成员只能通过实例化的对象来访问
console.log(ldh.uname);
// console.log(Star.uname);//不可以通过构造函数来访问实例成员
// 2.静态成员 在构造函数本身上添加的成员 sex就是静态成员
Star.sex = '男';
// 静态成员只能通过构造函数来访问
console.log(Star.sex);
</script>
- 子构造函数借用父构造函数继承属性
<script>
// 借用父构造函数继承属性
// 1. 父构造函数
function Father(uname, age) {
// this 指向父构造函数的实例对象
this.uname = uname;
this.age = age;
}
Father.prototype.money = function () {
console.log(10000000000);
}
// 2.子构造函数
function Son(uname, age, score) {
// this 指向子构造函数的对象实例
Father.call(this, uname, age);
this.score = score;
}
Son.prototype = new Father();
Son.prototype.constructor = Son;
// 这个是构造函数的专门方法
Son.prototype.exam = function () {
console.log('你好');
}
var son = new Son('刘德华', 56, 100);
console.log(son);
console.log(Father.prototype);
console.log(Son.prototype.constructors);
</script>
第二十一章、原型对象(prototype)
- 构造函数的原型对象
<script>
// 3.利用构造函数创建对象
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('我会唱歌');
}
let ldh = new Star('刘德华', 35);
let zxy = new Star('张学友', 35);
console.log(ldh.sing === zxy.sing);
ldh.sing();
zxy.sing();
// 构造函数创建对象的问题 实例化对象方法时会给每一个实例化对象方法开辟一个内存空间,浪费内存
// 解决方法给构造函数上添加一个原型对象在放方法
// 1.原型是什么:原型是一个对象
// 2.原型的作用:共享方法
// 注意:一般情况下,我们的公共属性定义到构造函数里面 ,公共的方法我们放到原型对象里面
</script>
- 实例化对象原型(--proto--)
<script>
// 3.利用构造函数创建对象
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('我会唱歌');
}
let ldh = new Star('刘德华', 35);
let zxy = new Star('张学友', 35);
ldh.sing();
console.log(ldh);//对象本身上系统自己添加一个__proto__指向我们的构造函数的原型对象
console.log(ldh.__proto__ === Star.prototype);
// 方法的查找规则:首先看ldh对象身上是否有sing方法,如果有就执行这个对象上的sing
// 如果没有sing这个方法,因为有__proto__的存在 就去构造函数原型对象prototype身上去查找sing这个方法
</script>
- 原型constructor指回对应的路线
<script>
// 3.利用构造函数创建对象
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
// 方法比较多可以以对象的形式来存储 如下我们需要手动的利用constructor 这个属性指回原来的构造函数
// Star.prototype.sing = function () {
// console.log('我会唱歌');
// };
// Star.prototype.move = function () {
// console.log('我会演电影');
// }
Star.prototype = ({
constructor: Star,//指回原来的构造函数就star
sing: function () {
console.log('我会唱歌');
},
movie: function () {
console.log('我会演电影');
}
})
let ldh = new Star('刘德华', 35);
let zxy = new Star('张学友', 35);
console.log(Star.prototype);
console.log(ldh.__proto__);
console.log(Star.prototype.constructor);
console.log(ldh.__proto__.constructor);
</script>
- 原型链
<script>
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
Star.prototype.sing = function () {
console.log('我会唱歌');
};
let ldh = new Star('刘德华', 35);
// 1.只要是对象就有__proto__原型,指向原型对象
console.log(Star.prototype);
console.log(Star.prototype.__proto__ === Object.prototype);
//2. 我们的star原型对象里面的__proto__原型指向的是Object.prototype
console.log(Object.prototype.__proto__);
</script>
5.原型中的this指向
<script>
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
var that;
Star.prototype.sing = function () {
console.log('我会唱歌');
that = this;
};
let ldh = new Star('刘德华', 35);
// 1.在构造函数中this指向的是对象实例 ldh
ldh.sing();
console.log(ldh === that);
// 2.原型链对象行数里面this指向的是实例对象 ldh
</script>
第三章、数组方法 迭代(遍历数组元素)的方法forEach,filter,some,map,every
- forEach迭代方法
<script>
// forEach 迭代(遍历)数组
var arr = [1, 2, 3]
arr.forEach(function (value, index, array) {
console.log('每个数组元素' + value);
console.log('每个数组元素的索引号' + index);
console.log('素组本身' + array);
})
</script>
- map迭代方法 和forEach相似
<script>
// map 迭代(遍历)数组
var arr = [1, 2, 3]
var sum = 0;
arr.map(function (value, index, array) {
sum += value;
console.log('每个数组元素' + value);
console.log('每个数组元素的索引号' + index);
console.log('素组本身' + array);
})
console.log(sum);
// 1、相同点
// (1)都是循环遍历数组中的每一项。
// (2)每次执行匿名函数都支持三个参数,参数分别为item(当前每一项),index(索引值),arr(原数组)。
// (3)匿名函数中的this都是指向window。
// (4)只能遍历数组。
// 2、不同点
// (1)map()会分配内存空间存储新数组并返回,forEach()不会返回数据。
// (2)forEach()允许callback更改原始数组的元素。map()返回新的数组.
</script>
3 filter迭代方法
<script>
// filter 筛选数组 (过滤数组是否满足条件 迭代(遍历))
// 返回的是一个新的数组不会影响原来的数组要用一个变量来接收
var arr = [16, 19, 44, 88, 3, 67];
console.log(arr);
var newArray = arr.filter(function (value, index, array) {
// 返回大于等于20的值
// return value >= 20;
// 返回所有的偶数
return value % 2 === 0
})
console.log(newArray);
</script>
- some迭代方法
<script>
// some方法 查找数组中是否有满足条件的元素 返回的是boolean值 有返回true 没有返回false
// 如果查到有一个元素满足条件就终止循环 不再继续查找
// 查找唯一的元素
var arr = [10, 30, 4];
var flag = arr.some(function (value, index, array) {
// 元素中是否存在大于剩余20的值
return value >= 20;
})
console.log(flag);
// 总结:
// 1.filter 也是查找元素满足条件的元素 返回的是一个数组 而且是把所有满足条件的元素返回回来的
// 2.some 也是查找元素满足条件的元素是否存在 返回的是一个布尔值 如果查找到元素第一个满足条件的元素就终止循环
</script>
- every迭代方法和some相似
<script>
// every和some相似 迭代(遍历)数组
var arr = [10, 30, 4];
var flag = arr.every(function (value, index, array) {
// 元素中是否存在大于剩余20的值
return value >= 30;
})
console.log(flag);
</script>
- some和forEach区别
<script>
var arr = ['red', 'green', 'blue', 'pink'];
// 1.forEach迭代(遍历)
arr.forEach(function (value, index) {
if (value == 'green') {
console.log('找到元素了');
return true;//forEach里面return 不会终止迭代
}
console.log(33);
})
// 如果查询数组中唯一的元素,用some方法更合适
arr.some(function (value, index) {
if (value == 'green') {
console.log('找到元素了');
return true;//some 里面 遇见return true 就会终止遍历 迭代效率更高
}
console.log(33);
})
arr.filter(function (value, index) {
if (value == 'green') {
console.log('找到元素了');
return true;//filter 里面 遇见return 不会终止迭代
}
console.log(33);
})
</script>
- 以上方法相关案例
<style>
table {
width: 400px;
border: 1px solid #000;
border-collapse: collapse;
margin: 0 auto;
}
td,
th {
border: 1px solid #000;
text-align: center;
}
input {
width: 50px;
}
.search {
width: 600px;
margin: 20px auto;
}
</style>
<body>
<div class="search">
按照价格查询: <input type="text" class="start"> - <input type="text" class="end"> <button
class="search-price">搜索</button> 按照商品名称查询: <input type="text" class="product"> <button
class="search-pro">查询</button>
</div>
<table>
<thead>
<tr>
<th>id</th>
<th>产品名称</th>
<th>价格</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
<script>
// 利用新增数组方法操作数据
var data = [{
id: 1,
pname: '小米',
price: 3999
}, {
id: 2,
pname: 'oppo',
price: 999
}, {
id: 3,
pname: '荣耀',
price: 1299
}, {
id: 4,
pname: '华为',
price: 1999
},];
//1. 获取元素
var tbody = document.querySelector('tbody');
var searchPrice = document.querySelector('.search-price');
var start = document.querySelector('.start');
var end = document.querySelector('.end');
var product = document.querySelector('.product');
var searchPro = document.querySelector('.search-pro');
// 2.把数据渲染到页面中
setDate(data);
function setDate(myData) {
// 先清空原来tbody里面的数据
tbody.innerHTML = '';
myData.forEach(function (value) {
console.log(value);
var tr = document.createElement('tr');
tr.innerHTML = `<td>${value.id}</td><td>${value.pname}</td><td>${value.price}</td>`;
tbody.appendChild(tr);
});
}
// 3.根据价格查询商品
// 当我们点击了按钮,就可以根据我们的商品价格去筛选数组里面的对象
searchPrice.addEventListener('click', function () {
var newDate = data.filter(function (value) {
// console.log(value);
// 判断条件 对象里面的价格>=开始表单里面的价格 并且 对象里面的价格<=结束表单里面的价格
return value.price >= start.value && value.price <= end.value;
})
// console.log(newDate);
// 把筛选完的对象渲染到页面中
setDate(newDate);
});
// 4.根据商品名称查找数据 用some方法更合适 ,因为它找到这个元素,就不再进行循环,效率更高
searchPro.addEventListener('click', function () {
var arr = [];
data.some(function (value) {
if (value.pname === product.value) {
// console.log(value);
arr.push(value);
return true; //return 后面必须写true
}
})
// 把拿到的数据渲染到页面中
setDate(arr);
console.log(arr);
})
</script>
</body>
第四章、内置对象新增的方法
- 数组
<script>
// 只能以点的形式追加方法 不能以对象的形式追加不让会覆盖原来的原型对象
Array.prototype.sum = function () {
var sum = 0;
for (var i = 0; i < this.length; i++) {
sum += this[i]
}
return sum;
}
var arr = [1, 23, 56];
console.log(arr.sum());
</script>
- trim方法去除字符串两边的空格
<body>
<input type="text">
<button>点击</button>
<div></div>
</body>
<script>
// trim方法 去除字符串两边的空格 返回的是一个新的字符串
// var str = ' andy ';
// console.log(str);
// var str1 = str.trim()
// console.log(str1);
var input = document.querySelector('input');
var button = document.querySelector("button");
var div = document.querySelector("div")
button.onclick = function () {
var str = input.value.trim();
if (str === '') {
alert('请输入内容');
} else {
console.log(str);
div.innerHTML = str;
}
}
</script>
第五章、修改和定义对象的原有属性( Object.defineProperty())方法
<script>
// Object.defineProperty() 定义新的属性或者修改原有的属性
var obj = {
id: 1,
pname: "小米",
price: 99
}
// 1.以前的对象添加和修改属性方法
// obj.num = 1000;
// obj.price = 99;
// console.log(obj);
//2. Object.defineProperty() 定义新的属性或者修改原有的属性
Object.defineProperty(obj, 'num', {
value: 1100,
enumerable: true,
});
console.log(obj);
Object.defineProperty(obj, 'price', {
value: 9.9
});
console.log(obj);
Object.defineProperty(obj, 'id', {
// false不予许修改这个属性 为true可以修改
writable: false,
});
obj.id = 2;
console.log(obj);
Object.defineProperty(obj, 'address', {
value: '中国昆明XXX',
// enumerable 如果值为false 则不育性遍历 默认的值是false
enumerable: false,
// configurable 如果为false则不予许删除这个属性 不予许修改第三个属性 默认为false
configurable: false
});
console.log(Object.keys(obj));// keys也是遍历数组的方法
delete obj.address
console.log(obj);
delete obj.pname
console.log(obj);
// 语法格式:
/* 2. Object.defineProperty()定义新属性或修改原有的属性。
object. det ineProperty(obj, prop, descriptor)
Object defineProperty(第三个参数descriptor说明:以对象形式{} 书写
●value:设置属性的值默认为undefined
●writable:值是否可以重写。true | false 默认为false
●enumerable;目标属性是否可以被枚举。true | false默认为false
●configurable:目标属性是否可以被删除或是否可以再次修改特性true | false 默认为false */
</script>
第六章、函数
- 函数的定义
<script>
// 1.自定义函数(命名函数)
function fn() { };
// 2.函数表达式(匿名函数)
var fun = function () { };
// 3.利用 new Function('参数1','参数2','参数3','函数体');
var f = new Function('a', 'b', 'console.log(a+b)');
f(1, 3);
// 4.所有函数都是Function 的实例(对象)
console.dir(f);
// 函数也属于对象
console.dir(f instanceof Object);
</script>
- 函数的调用
<script>
// 1.普通函数
function fn() {
console.log('人生的巅峰');
}
fn(); //fn.call();
// 2.对象的方法里面的函数
var o = {
sayH: function () {
console.log('人生的巅峰');
}
}
o.sayH();
// 3.构造函数
function Star() { }
new Star();
// 4.绑定事件函数
btn.onclick = function () { } //点击了按钮时调用
// 5.定时器函数
setInterval(function () { }, 1000);//这个函数是定时器每个1秒钟调用一次
// 6.立即执行函数
(function () {
console.log('人生的巅峰');
})()
// 立即执行函数是自动调用的
</script>
第七章、this的指向
<script>
// 函数的不同调用方式决定了this 的指向不同
// 1.普通函数 this 指向 window
var btn = document.querySelector('button')
function fn() {
console.log('普通函数的this:' + this);
}
window.fn();
// 2.对象的方法里面的函数 this 指向的是对象 li
var li = {
sayH: function () {
console.log('对象方法的this:' + this);
}
}
li.sayH();
// 3.构造函数 this 指向 ldh 这个实例对象 原型对象里面的this 指向的也是ldh这个实例对象
function Star() { }
Star.prototype = function () { }
var ldh = new Star();
// 4.绑定事件函数 this 指向的是函数的调用者 btn这个按钮对象
btn.onclick = function () {
console.log('绑定时间函数的this:' + this);
}
// 5.定时器函数 this 指向的也是window
window.setInterval(function () {
console.log('定时器的this:' + this);
}, 1000);
// 6.立即执行函数 this 还是指向 window
(function () {
console.log('立即执行函数的this:' + this);
})()
</script>
第八章、改变this的指向有(call,bind,apply方法)
- call方法
<script>
// 改变函数内this指向 js 提供了三种方法 call() apply() bind()
// 1.call() 呼叫的意思
var o = {
name: "andy"
}
function fn(a, b) {
console.log(this);
console.log(a + b);
}
fn.call(o, 1, 2);
// call() 作用 :
// 1.可以调用函数
// 2.可以改变函数内this的指向
// 3.主要作用可以实现继承
// 父类构造函数
function Father(uname, age, sex) {
this.uname = uname;
this.age = age;
this.sex = sex;
}
// 子类构造函数 继承父类里面的属性
function Son(uname, age, sex) {
Father.call(this, uname, age, sex)
}
var son = new Son('刘德华', 58, '男');
console.log(son);
</script>
- apply方法
<script>
// 改变函数内this指向 js 提供了三种方法 call() apply() bind()
// apply() 应用 运用的意思
var o = {
name: "andy"
};
function fn(arr) {
console.log(this);
console.log(arr);// 'pink'
};
fn.apply(o, ['pink'])
// apply() 作用 :
// 1.可以调用函数
// 2.可以改变函数内this的指向
// 3.但是他的参数必须是数组(伪数组)
// 4.apply的主要作用 可以利用apply 借助于数学内置对象求最大值
var arr = [166, 3, 99, 4];
var max = Math.max.apply(Math, arr);
console.log(max);
// 2. apply方法
// apply)方法凋用一个函数。 简单理解为调用函数的方式,但是它可以改变函数的this指向。
// fun. apply (thisArg, [argsarray1)
// ●thisArg :在fun函数运行时指定的this值
// ●argsArray :传递的值,必须包含在数组里面
// ●返回值就是函数的返回值,因为它就是调用函数
</script>
- bind方法
<body>
<button>点击</button>
<button>点击</button>
<button>点击</button>
<button>点击</button>
<button>点击</button>
<script>
// 改变函数内this指向 js 提供了三种方法 call() apply() bind()
// bind() 绑定 捆板的意思
var o = {
name: "andy",
};
function fn(a, b) {
console.log(this);
console.log(a + b);
};
var f = fn.bind(o, 1, 2);
f();
// 1.不会调用原来的函数 可以改变原来函数内部的this指向
// 2.返回的是原函数改变this之后产生的新函数
// 3.如果有的函数我们不需要立即调用, 但是又想改变这个函数内部的thiS指向此时用bind
// 4.我们有个按钮,当我们点击了之后,就禁用这个按钮,3秒钟之后开启这个按钮
// var btn = document.querySelector("button");
// btn.onclick = function () {
// this.disabled = true;
// setTimeout(function () {
// this.disabled = false;//此时定时器函数里面的this指向的是btn
// }.bind(this), 3000);//this 指向的是 btn 这个对象
// }
var btnS = document.querySelectorAll("button");
for (var i = 0; i < btnS.length; i++) {
btnS[i].onclick = function () {
this.disabled = true;
setTimeout(function () {
this.disabled = false;
}.bind(this), 2000)
}
}
/*
3. bind方法
bind)方法不会调用函数。但是能改变函数内部this指向
Lun. bind (LhisArg, arg1, arq2, ...1
●thisArg :在fun函数运行时指定的this值
●arg1 , arg2 :传递的其他参数
●返回由指定的this值和初始化参数改造的原函数拷贝 */
</script>
</body>
- call apply bind 总结
<script>
call apply bind 总结
相同点:
都可以改变函数内部的this指向.
区别点:
1. call和apply会调用函数,并且改变函数内部this指向.
2. call 和apply传递的参数不一样, call传递参数aru1, a..形式apply 必须数组形式[arg]
3. bind 不会调用函数可以改变函数内部this指向.
主要应用场景;
1. call 经常做继承.
2. apply 经常跟数组有关系比如借助于数学对象实现数组最大值最小值
3. bind 不调用函数但是还想改变this指向.比如改变定时器内部的this指向.
</script>
第九章、严格模式
- 开启严格模式
<!-- 为整个脚本(script标签)开启严格模式 -->
<script>
'use strict';
//下面的js代码就会按照严格模式执行代码
</script>
<script>
// 为立即执行函数添加严格模式
(function () {
'use strict';
})();
</script>
<!-- 为某个函数开启严 格模式 -->
<script>
// 此时只是为fn开启严格模式
function fn() {
'use strict';
// 下面的代码按照严格模式执行
}
function fun() {
// 里面的还是按照普通函数执行
}
</script>
- 严格模式的变化
<script>
'use strict';
// 1.我们的变量必须先声明在使用
num = 10;
console.log(num);
var num = 10;
console.log(num);
// 2.不能随意删除已经声明好的变量
delete num;
// 3.严格模式下全局作用域函数中 this 指向的是 undefined
function fn() {
console.log(this);//undefined
}
fn();
// 4. 严格模式下 如果构造函数不加new调用 this会报错 如果用new调用 this指向的是实例化对象
function Star() {
this.sex = '男';
}
Star();
var ldh = new Star();
console.log(ldh);
// 5.严格模式下定时器 this 还是指向的是window
setTimeout(function () {
console.log(this);
}, 2000)
// 严格模式下函数里面的参数不能有重名 以下函数代码执行会报错
function fn(a, b) {
console.log(a + a);
}
fn(1, 2)
等等
</script>
第十章、高阶函数
<script>
// 高阶函数:传递过来的参数是函数 return的值是函数就称为高阶函数
// 简单的说:函数可以作为参数传递
function fn(a, b, callback) {
console.log(a + b);
callback && callback();
}
fn(1, 2, function () {
console.log('我是最后调用的函数');
});
</script>
第十一章、闭包函数
- 什么是闭包函数
<script>
// 闭包 (closure) 指有权访问另一个函数作用域中变量的局部变量
// 闭包 :我们fun 这个函数作用域 访问了另一个函数fn 里面的局部变量 num
function fn() {
var num = 10;
function fun() {
console.log(num);
}
fun();
}
fn();
</script>
- 闭包函数的作用
<script>
// 我们fn 外面的作用域可以访问fn 内部的局部变量
// 闭包的主要作用:延生了变量的作用范围
function fn() {
var num = 10;
function fun() {
console.log(num);
}
return fun;
}
var f = fn();
f();
</script>
- 闭包函数的案例
<body>
<ul class="nav">
<li>世界美男子</li>
<li>世界美男子</li>
<li>世界美男子</li>
<li>世界美男子</li>
<li>世界美男子</li>
</ul>
<script>
// 闭包应用点击li输出当前li的索引号
// 1.我们可以利用动态的添加属性的的方式
var lis = document.querySelector(".nav").querySelectorAll("li");
// for (var i = 0; i < lis.length; i++) {
// lis[i].index = i
// lis[i].onclick = function () {
// console.log(this.index);
// }
// }
// 2.利用闭包的方式得到当前的小li 的索引号
for (var i = 0; i < lis.length; i++) {
// 立即执行函数也成为小闭包因为立即执行函数里面的任何一个函数都可以使用它的li的变量
(function (i) {
// console.log(i);
lis[i].onclick = function () {
console.log(i);
};
})(i)
}
</script>
- 闭包函数用于定时器
<body>
<ul class="nav">
<li>世界美男子</li>
<li>世界</li>
<li>宇宙</li>
<li>远方</li>
<li>人间烟火</li>
</ul>
<script>
// 1.闭包应用-3秒钟之后,打印所有li元素的内容
var lis = document.querySelector(".nav").querySelectorAll("li");
for (var i = 0; i < lis.length; i++) {
(function (i) {
setTimeout(function () {
console.log(lis[i].innerHTML);
}, 3000)
})(i)
}
</script>
</body>
- 闭包函数用于打车价格
<script>
//打车起步价13(3公里内), 之后每多一公里增加5块钱. 用户输入公里数就可以计算打车价格
//如果有拥堵情况,总价格多收取10块钱拥堵费
var car = (function () {
var start = 13;
var total = 0;
return {
// 正常的价格
price: function (n) {
if (n <= 3) {
total = start;
} else {
total = start + (n - 3) * 5;
}
return total;
},
// 拥堵的费用
yd: function (flag) {
return flag ? total + 10 : total;
}
}
})();
console.log(car.price(5));//23
console.log(car.yd(true));//33
</script>
- 闭包思考题
<script>
// 思考一 没有闭包产生
var name = 'The Window';
var Object = {
name: 'My Object',
getNameFunc: function () {
return function () {
return this.name;
};
}
};
console.log(Object.getNameFunc()()); //这个拆分为一下 输出: The Window
var f = Object.getNameFunc();
// 类似于
// var f = function () {
// return this.name;
// }
// f();
// 思考二 有闭包产生
var name = 'The Window';
var Object = {
name: 'My Object',
getNameFunc: function () {
var that = this;
return function () {
return that.name;
};
}
};
console.log(Object.getNameFunc()()); // 输出: My Object
</script>
第十二章、递归函数
- 什么是递归函数
<script>
// 递归:函数内部自己调用自己称为递归函数
// 注意点:递归函数作用和循环效果一样 由于递归很容易出 栈溢出 错误 所以必须要加退出条件 return
var num = 1;
function fn() {
console.log('我要打印六句话');
if (num == 6) {
return;//递归里面必须加退出条件
}
num++;
fn()
}
fn();
</script>
- 递归函数求1~n的阶乘
<script>
// 利用递归函数求1~n的阶乘 1*2*3*4*....n
function fn(n) {
if (n == 1) {
return 1;
}
return n * fn(n - 1);
}
console.log(fn(3));
console.log(fn(4));
console.log(fn(109));
//运行过程:加入用户输入的是3
//return 3 * fn(3 - 1)
//return 3 * fn(2)
//return 3 * fn(2 * fn(2-1))
//return 3 * fn(2 * fn(1))
//return 3 * fn(2 * 1)
//return 3 * (2)
//return 6
</script>
- 利用递归函数求斐波那契数列
<script>
//利用递归函数求斐波那契数列(兔子序列) 1、1、2、3、5、8、13、 21. . .
//用户输入一个数字n就可以求出这个数字对应的兔子序列值
//我们只需要知道用户输入的n的前面两项(n-1 n-2)就可以计算出n对应的序列值
function fb(n) {
if (n === 1 || n === 2) {
return 1;
}
return fb(n - 1) + fb(n - 2);
}
console.log(fb(3));
console.log(fb(6));
</script>
- 利用递归函数遍历数据
<script>
var date = [{
id: 1,
name: "家电",
goods: [{
id: 11,
gName: '冰箱',
goods: [{
id: 111,
gName: '海尔'
}, {
id: 111,
gName: '美的'
},]
}, {
id: 12,
gName: '洗衣机'
}]
}, {
id: 2,
name: '手机',
}]
// 我们想要做输入id浩 就可以返回的数据对象
// 1.利用forEach 去遍历里面的每一个对象
function getID(json, id) {
var o = {};
json.forEach(function (item) {
if (item.id == id) {
// console.log(item);
o = item;
// 2.我们想要得到里层的数据 可以用递归函数
} else if (item.goods && item.goods.length > 0) {
o = getID(item.goods, id);
}
});
return o;
}
console.log(getID(date, 1));
console.log(getID(date, 2));
console.log(getID(date, 11));
console.log(getID(date, 12));
console.log(getID(date, 111));
</script>
第十三章、深拷贝与浅拷贝
- 深拷贝
<script>
// 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝地址 修改拷贝过来的数据 旧的也被修改.
// 2.深拷贝拷贝多层,每一级别的数据都会拷贝.
var obj = {
id: 1,
name: 'andy',
msg: {
age: 11,
},
color: ['pink', 'red']
};
var o = {};
// 封装函数
function deepCopy(newObj, oldObj) {
for (var k in oldObj) {
// 1.判断我们的数据类型属于那种数据类型
var item = oldObj[k];
// 2.判断这个值是否是数组
if (item instanceof Object) {
newObj[k] = [];
deepCopy(newObj[k], item);
} else if (item instanceof Object) {
// 3. 判断这个值是否是对象
newObj[k] = {};
deepCopy(newObj[k], item);
} else {
// 4.属于简单数据类型
newObj[k] = item;
}
}
}
deepCopy(o, obj);
console.log(o);
</script>
- 浅拷贝
<script>
// 1.浅拷贝只是拷贝一层,更深层次对象级别的只拷贝地址 修改拷贝过来的数据 旧的也被修改.
// 2.深拷贝拷贝多层,每一级别的数据都会拷贝.
var obj = {
id: 1,
name: 'andy',
msg: {
age: 18
}
};
console.log(obj);
var o = {};
// 第一种方式 用for in循环拷贝
// for (var k in obj) {
// // k 属性名 boj[k]属性值
// o[k] = obj[k]
// }
// console.log(o);
// 第二种方式 Object.assign(target,obj)
Object.assign(o, obj);
// 拷贝后修改里面的值外面的值也改变了
o.msg.age = 20;
console.log(o);
</script>
第十四章、正则表达式
- 正则表达式语法
<script>
// 正则表达式在js中的使用
// 1. 利用RegExp对象来创建正则表达式
var regExp = new RegExp(/123/);
console.log(regExp);
// 2.利用字面量来创建正则表达式
var rg = /123/;
// test() 方法用来检测字符串是否符合正则表达式要求的规范 符合返回true 不符合返回的是false
console.log(rg.test(123));
// 3. 边界符 ^ $ 开始 结束
// 4.字符类:[] 表示一系列字符可供选择 只要匹配其中一个就可以 为true 其余为false
// 5.范围:- 表示a到z的范围 为true 其余为false
// 6.[^]:中括号里面的 ^ 表示取反
// 7.量词符: * 表示可出现0次或者多次 为true 其余为false
// 8.量词符: + 表示可出现大于等于1次或者很多次 为true 其余为false
// 9.量词符: ? 表示可出现0次或者1次 为true 其余为false
// 10. a{3}: 表示重复三次 为true 其余为false
// 11. a{3,}: 表示重复大于等于三次 为true 其余为false
// 12. a{3,16}: 表示重复大于等于3次 并且小于等于16 为true 其余为false
// 13. (): 表示优先级
// 14. \d: 表示0-9
// 15. \D: 表示所有0-9以外的数字
// 16. \w: 表示匹配任意字母,下划线,数字
// 17. \W:除所有字母、数字和下划线以外的字符,相当于[^ A - Za - z0 -9_]
// 18. \s:匹配空格(包括换行符、制表符、空格符等), 相等于[\t\r\n\v\f]
// 19. \S:匹配非空格的字符, 相当于[^ \t\r\n\v\f]
// 20. | :表示或者的意思
// 21. g : 表示全局匹配
// 22. i : 忽略大小写
// 23. gi :忽略大小写和全局匹配
</script>
- 座机案例
<script>
// 座机号码验证: 全国座机号码 两种格式 :010-12345678 或者 0530-1234567
// var reg = /^\d{3}-\d{8}|\d{4}-\d{7}$/;
var reg = /^\d{3,4}-\d{7,8}$/;
console.log(reg.test("1234-12345674"));
</script>
3. 正则表达式过滤明感词
<body>
<textarea name="" id="" cols="30" rows="10"></textarea>
<button>提交</button>
<div></div>
<script>
// 替换 replace('m','n') m表示的是被替换的词 n替换为什么
// var str = 'and和red';
// var newS = str.replace("and", 'ldh');
// var newS = str.replace(/blue/, 'ldh');
// console.log(newS);
var text = document.querySelector("textarea");
var button = document.querySelector('button');
var div = document.querySelector('div');
button.onclick = function () {
div.innerHTML = text.value.replace(/激情|床上/g, '****')
}
</script>
</body>
第十五章、var let const关键字
<script>
1. let 关键字是用来声明变量的
(1).let 关键字声明的变量具有块级作用域 {}这个范围内有效超出会报错
(2).let 防止循环变量变成全局变量
(3).let 声明的变量不存在变量提升
(4).let 关键字声明的变量具有暂时性死区特性
2.var关键字是用来声明变量的
(1). var 关键字声明的变量是全局作用域
(2). var 声明的变量存在变量提升
(3). var 不具有块级作用域的特点
3.const 关键字是用来声明常量的
(1). const 关键字声明的常量具有块级作用域
(2). const 关键字声明的常量必须要赋初始值
(3). const 关键字声明的常量赋值后基本数据类型 不能修改值 复杂数据类型内部的值是可以更改的但是不可以重新赋值
</script>
第十六章、解构赋值
- 数组解构赋值
<script>
// 数组解构允许我们按照一一对应的关系从数组中提取数据然后将值赋值给变量 如果没有对应的值为undefined
let arr = [1, 2, 3, 4];
let [a, b, c, d, e] = arr;
console.log(a);
console.log(b);
console.log(c);
console.log(d);
console.log(e);
</script>
- 对象解构赋值
<script>
// 对象解构允许我们使用变量的名字匹配对象的属性 匹配成功将对象的属性值赋值给变量
let person = { name: 'li', age: 18, sex: '男' };
// 第一种方法
// let { name, age, sex } = person;
// console.log(name);
// console.log(age);
// console.log(sex);
// 第二种方法
let { name: myName,age:myAge,sex:mySex} = person;
console.log(myName);
console.log(myAge);
console.log(mySex);
</script>
第十七章、箭头函数
<script>
// 箭头函数特点
// 1.箭头函数的调用用用声明的变量来调用
// 2. 函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
// 3.如果形参只有一个, 可以省略小括号
// 4.箭头函数没有自己的this关键字 如果在箭头函数中使用this关键字 则指向箭头函数定义位置中的this
// 1.箭头函数的调用用用声明的变量来调用
// const fn = () => {
// console.log(123);
// }
// fn();
// 2. 函数体中只有一句代码,且代码的执行结果就是返回值,可以省略大括号
// const sum = (n1, n2) => n1 + n2;
// const result = sum(10, 20);
// console.log(result);
// 3.如果形参只有一个, 可以省略小括号
// const fn = v => {
// console.log(33);
// }
// fn();
// 4.箭头函数没有自己的this关键字 如果在箭头函数中使用this关键字 则指向箭头函数定义位置中的this
function fn() {
console.log(this);
return () => {
console.log(this);
}
}
const obj = { name: "zha" };
const res = fn.call(obj);
res();
// 5.剩余的参数
const sum = (...start) => {
let total = 0;
start.forEach((item) => {
total += item
})
return total;
}
console.log(sum(10, 20));
console.log(sum(10, 20, 30));
</script>
第十八章、扩展运算符
- 什么是扩展运算符
<script>
// 扩展运算符可以将数组拆分成以逗号分隔的参数序列
let ary = ["a", "b", "c"];
//...ary //a, b, c
console.log(...ary);
</script>
2. 扩展运算符合并数组
<script>
// 1.扩展运算符可以将数组合并成以逗号分隔的参数序列
// 合并数组的第一种方法
let ary1 = ["a", "b", "c"];
let ary2 = ["pink", "blue", "red"];
// ...ary // a, b, c
// ...ary1 // pink, blue, red
let ary3 = [...ary1, ...ary2];
console.log(ary3);
//2. 合并数组的第二种方法
let arr1 = [1, 2, 3, 4];
let arr2 = [5, 6, 7, 8, 9];
arr1.push(...arr2);
console.log(arr1);
//3. 利用扩展运算符将伪数组转换为真正的数组
// 为什么我们要将伪数组转换为真正的数组? 因为可以使用数组里面的方法
var odiv = document.getElementsByTagName('div');
console.log(odiv);
var ary = [...odiv];
console.log(ary);
</script>
第十九章、Array对象里面的方法(from,find,findindex,includes)
- from方法
<script>
// 将对象里面的伪数组转换为正真的数组 Array.from(arr,fn) 有两个参数 第二个参数是一个函数
let arr = {
"0": '我',
"1": '爱',
"2": '你',
"length": 3
}
var ary = Array.from(arr);
console.log(ary);
// 将对象里面的伪数组转换为正真的数组 Array.from(arr,fn) 有两个参数 第二个参数是一个函数
let arr1 = {
"0": '2',
"1": '4',
"2": '6',
"length": 3
}
var ary = Array.from(arr1, function (item, index) {
return item * 2;
});
console.log(ary);
</script>
- find方法
<script>
// find()用于找出第一个符合条件的数组成员,如果没有找到返回undefined
// 需求 查找id为2的元素
let ary = [{
id: 1,
name: '张三'
}, {
id: 2,
name: '李四'
}]
// let target = ary.find(item => item.id === 2); 以下写法入上
let target1 = ary.find(function (item) {
return item.id === 2;
})
console.log(target1);
</script>
- findindex方法
<script>
// findIndex()用于找出第一个符合条件的数组成员的位置,如果没有找到返回-1
// 需求 查找数组元素大于15的值在数组元素中的索引
let ary = [1, 45, 6];
let target1 = ary.findIndex(function (item, index) {
return item > 6;
})
console.log(target1);
</script>
- includes方法
<script>
//includes() 表示某个数组是否包含给定的值,返回布尔值,
let ary = ['a', 'b', 'c'];
let target1 = ary.includes('a');
console.log(target1);
</script>
- startWith方法
<script>
// ●startsWith0: 表示参数字符串是否在原字符串的头部,返回布尔值
// ●endsWith0: 表示参数字符串是否在原字符串的尾部,返回布尔值
let str = 'Hello ECMAScript!';
let r1 = str.startsWith('Hello');
console.log(r1);//true
let r2 = str.endsWith('2015');
console.log(r2);//false
</script>
- repeat方法
<script>
// repeat方法表示将原字符中重n复次。返会回一个新符串.
let string = 'hello';
let re= string.repeat(2);
console.log(re);
</script>
第二十章、模板字符
<script>
// `` 模板字符串为两个反引号
// 特点:
// 1.可以解析变量 用 ${} 括号里面写变量名
// 2.模板字符串可以换行
// 3.在模板字符串里面可以调用函数
// 1.可以解析变量 用 ${} 括号里面写变量名
let name = `李四`;
let say = `我的名字叫${name}`
console.log(say);
// 2.模板字符串可以换行
let result = {
name: "李四",
age: 19
}
let html = `
<div>
<span>${result.name}</span>
<span>${result.age}</span>
</div>
`;
console.log(html);
function fn() {
return '我是函数';
}
let html1 = `我是模板字符串${fn()}`;
console.log(html1);
</script>
第二十一章、set对象(数据结构)
- set结构里面的方法
<script>
// Set本身是一个构造函数,用来生成Set数据结构.
// 用size检测数据结构的值有几个
const s1 = new Set();
console.log(s1.size);
const s2 = new Set(['a', 'b']);
console.log(s2.size);
/*
add(value); 添加某个值,返回Sel结构本身
delete(value): 删除某个值,返回个布尔值, 示是否功
has(value): 返回一个布尔值,表示该值是否为Set的成员
clear: 清除所有成员,没有返回值
*/
const s3 = new Set();
s3.add(1).add(2)
console.log(s3);
s3.delete(1)
console.log(s3);
let index = s3.has(1);
console.log(index);
s3.clear();
console.log(s3.size);
</script>
- set可用于数组去重
<script>
// set数据结构数组去重
const s1 = new Set(['a', 'a', 'c', 'c']);
console.log(s1.size);
const s2 = [...s1]
console.log(s2);
</script>
- 遍历set对象
<script>
// set 对象的遍历里面 也有forEach方法
let arr = new Set(['pink', 'blue', 'red', 'yellow']);
arr.forEach((value) => {
console.log(value);
})
</script>
标签:function,ES6,console,函数,let,var,log
From: https://www.cnblogs.com/dexue/p/16952094.html