day01
1.对象的创建方式
// 1.字面量创建方式
var obj = {
// 键:值对(属性:属性值)
name: "小好",
age: 18,
gender: "男"
}
console.log(obj);
// 2.利用 Object构造函数
var obj2 = new Object();
obj2.name = "小谷";
obj2.age = 18;
obj2['gender'] = "女";
console.log(obj2);
// 3.利用自定义构造函数
function Person(name, age, gender) {
// this - 实例化对象
this.name = name;
this.age = age;
this.gender = gender;
}
var obj3 = new Person("张三", 19, "男");
console.log(obj3);
// 遍历对象
for (var key in obj3) {
console.log(key);
console.log(obj3[key]);
}
2.Object.keys
Object.keys(obj)该方法会将一个给定对象自身的可枚举的属性添加到一个数组里面进行返回
3.Object.getOwnPropertyNames
Object.getOwnPropertyNames(obj)方法 该方法返回一个由指定对象的所有自身属性的属性名组成的数组。
4.检查对象的属性是否存在
in 在 。。。里面
console.log('name' in obj3);
判断数组里面是否包含该数据
var arr = [1, 2, 3, 5, 6, 67];
console.log(2 in arr);
5.删除对象的属性
需要通过 delete 这个关键字删除对象的属性
delete obj3.name
console.log(obj3);
6.对象的数据属性和访问器的属性
对象的属性分为两种
数据属性:用来存放一个值或是一组数据
访问器属性: 不包含值,而是定义了一个get函数和set函数 当读取属性时 get会调用 设置属性时 set会调用
访问器属性:get getName()
set setName(value)
设置属性:obj.setName = "普京"
7.对象的属性特征
用来配置对象属性的特征信息
Object.defineProperty(obj, prop, descriptor)
obj:目标对象
prop:要修改的属性
descriptor : 修改当前属性的特征
Object.defineProperty(obj, 'gender', {
// 康菲个弱bou
configurable: true,
// 欸牛么瑞bou
enumerable: true,
// ruai特bou
writable: true,
// value: "男"
})
configurable : 是否可被删除
enumerable : 是否可被枚举
writable : 是否可被修改
value :当前值
8.修改多个属性特征
Object.defineProperties(obj, prop)
9.获取属性的特征
bject.getOwnPropertyDescriptor(obj, prop)
返回目标对象内部的某一个属性的特征 返回值是一个对象
obj:目标对象
prop:目标对象内的某个属性
获取多个
Object.getOwnPropertyDescriptors(obj)
day02
1.普通函数和构造函数
普通函数--主要用来封装 处理业务逻辑
function fun(形参){
// 代码块
// this(window)
// arguments(参数集合-伪数组)
}
fun(实参);
构造函数--批量实例化对象
function Create(name, age, gender) {
// this--实例化对象
// arguments
this.name = name;
this.age = age;
this.gender = gender
}
var per = new Create("小谷", 18, "男");
console.log(per);
2.构造函数的实例成员和静态成员
实例成员-在构造函数内部添加的成员 只能通过实例化对象访问
静态成员-在构造函数本身上添加的成员--只能通过构造函数访问
3.构造函数的原型
S规定每一个构造函数都有一个属性叫 prototype 它是一个对象
称为构造函数的 原型对象
4.对象原型
每一个对象都一个__proto__属性这个属性就是对象的原型
对象身上的__proto__ == 构造函数的prototype
因此可以在对象身上访问到 Create.prototype.rap
原型:
构造函数 身上是 prototype 称为 原型对象
对象身上时 __proto__ 称为 对象的 原型
原型链:
对象在查找一个属性的时候,会先在自身查找,如果没有找到
就会在对象的原型(__proto__ )上查找就是构造函数的prototype
如果还没有找到就会去构造函数的prototype 的__proto__身上查找
直到查找到Object 这样一层一层向上查找形成一个链式结构称为原型链
最后没找到 返回 null 控制台打印的是undefined
5.构造函数constructor
Object.prototype.hasOwnProperty(prop)方法
可以判断一个属性定义在对象本身而不是继承原型链的方法,
主要用于判断某个对象中是否有某个属性,返回值为布尔值。
console.log(Object.prototype.hasOwnProperty('name'));
console.log(per.hasOwnProperty('name'));
console.log(per.hasOwnProperty('height'));
console.log(per.hasOwnProperty('rap'));
Object.prototype.isPrototypeOf(Object)方法
isPrototypeOf方法接收一个对象,
用来判断当前对象是否在传入的参数对象的原型链上,
返回一个布尔值
console.log(Object.prototype.isPrototypeOf(date));
console.log(Object.prototype.isPrototypeOf(reg));
console.log(Object.prototype.isPrototypeOf(num));
console.log(Object.prototype.isPrototypeOf(obj));
day03
1.this指向
1.普通函数---window
2.自执行函数---window
3.定时器---window
4.对象方法中的this--该方法所属对象
5.事件中的this----事件源
6.构造函数--实例化对象
<script>
var box = document.querySelector(".box");
// 1.普通函数---window
function fun() {
console.log(this);
}
fun();
// 2.自执行函数---window
(function () {
console.log(this);
})();
// 3.定时器---window
setTimeout(function () {
console.log(this);
}, 100)
// 4.对象方法中的this--该方法所属对象
var obj = {
name: "张三",
sayHi: function () {
console.log(this);
}
}
obj.sayHi();
// 5.事件中的this----事件源
box.onclick = function () {
console.log(this);
}
// 6.构造函数--实例化对象
function Fun() {
console.log(this);
}
// 7.构造函数原型对象上的函数 this-----实例化对象
Fun.prototype.run = function () {
console.log(this);
}
var p1 = new Fun();
p1.run();
</script>
2.改变this指向
call():使用一个指定的 `this` 值调用一个函数
①call会立即调用函数
②参数传递的方式是以逗号隔开
③可以改变this指向
apply()
①apply会立即调用函数
②传入参数是以数组形式
③改变this指向
bind()
①bind不会立即调用 需要手动调用
②传入参数以逗号隔开
③改变this指向
3.call应用场景检测数据类型
1.typeof 检测基本数据类型
console.log(typeof num);
console.log(typeof str);
2.instanceof
console.log(new Date instanceof Object);
console.log(new RegExp instanceof Object);
3.constructor
console.log(obj.constructor == Object);//true
console.log(date.constructor == Date);//true
4.Object.prototype.toString.call 最精准的检测方式
console.log(Object.prototype.toString.call(123));
console.log(Object.prototype.toString.call(arr));
面试题 JS检测数据类型的方式有几种?
1.typeof 检测基本数据类型
2.instanceof 检测复杂数据类型
3.constructor 检测构造函数类型
4.Object.prototype.toString.call() 最精准的检测方式
4-apply应用场景-math
var arr = [56, 66, 2, 11, 67, 45];
var rel2 = Math.max.apply(Math, arr);
console.log(rel2);
5-bind应用场景
var btn = document.querySelectorAll("button");
// var timerId = null;
for (var i = 0; i < btn.length; i++) {
btn[i].onclick = function () {
this.disabled = true;
var num = 5;
var timerId = setInterval(function () {
num--;
if (num <= 0) {
this.disabled = false;
this.innerText = "5秒之后再次点击";
clearInterval(timerId);
} else {
this.innerText = num + "秒之后再次点击";
}
}.bind(this), 1000);
}
}
6.定时器传参
解决定时器不能传参的问题
在外部封装函数 写在定时器方法里面进行调用
注意:要用引号将函数包括
setTimeout("fun(k)", 2000);
function fun(i) {
console.log(k);
}
7.forEach数组操作方法
arr.forEach(function (value, index, arr) {
// value当前元素
// index元素的索引
// arr当前数组
})
forEach没有返回值
8.map数组操作方法
var arr = [1, 2, 3, 5, 6, 7, 89];
// 遍历数组
var rel = arr.map(function (value, index, arr) {
// value当前元素
// index元素的索引
// arr当前数组
console.log(value + "-----" + index);
console.log(arr);
return "操作元素" + value
})
map 具有返回值
注意:map() 不会对空数组进行检测, map() 不会改变原始数组。
9.filter数组操作方法
filter 过滤 方法创建一个数组,将满足条件的元素添加到新数组中返回
var rel = arr.filter(function (value, index, arr) {
// value当前元素
// index元素的索引
// arr当前数组
console.log(value);
// 具有返回值
return value > 50
})
console.log(rel);
10some数组操作方法
some 查找数组中是否有满足条件的元素 ,如果数组中有元素满足条件返回 true,否则返回 false。
var arr = [56, 32, 78, 11, 23, 103, 45, 103];
// some 查找数组中是否有满足条件的元素 ,如果数组中有元素满足条件返回 true,否则返回 false。
var rel = arr.some(function (v) {
return v > 100
})
console.log(rel);
11every数组的操作方法
every() 方法用于检测数组所有元素是否都符合指定条件(通过函数提供)。
如果数组中检测到有一个元素不满足,则整个表达式返回false,且剩余的元素不会再进行检测。
所有元素都满足条件 才会返回true
var arr = [56, 32, 78, 11, 23, 103, 45, 103];
var rel = arr.every(function (v) {
console.log("zhixing");
return v < 100
})
console.log(rel);
12find数组的操作方法
// find() 方法返回通过测试(函数内判断)的数组的第一个元素的值。
// find() 方法为数组中的每个元素都调用一次函数执行:
// 如果没有符合条件的元素返回 undefined
var arr = [56, 32, 78, 11, 23, 103, 45, 103];
var rel = arr.find(function (v) {
console.log("执行");
return v > 100
})
console.log(rel);
13reduce数组的操作方法
reduce方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
array.reduce(function (total, value, index, array) {
// - total 必需。初始值, 或者计算结束后的返回值。
// value 必需。当前元素
// index 可选。当前元素的索引
// array可选。当前元素所属的数组对象。
// - initialValue 作为第一次调用 `callback`函数时的第一个参数的值。 如果没有提供初
//始值,则将使用数组中的第一个元素。
}, initialValue)
求和
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var rel1 = arr.reduce(function (total, value) {
return total + value
})
console.log(rel1);
求最大值
var arr2 = [45, 67, 12, 2, 103, 44, 33];
var rel2 = arr2.reduce(function (total, value) {
return Math.max(total, value);
})
console.log(rel2);
数组去重
var arr3 = [44, 65, 44, 12, 3, 2, 5, 2, 16];
var rel3 = arr3.reduce(function (total, value, index) {
if (!total.includes(value)) {
total.push(value);
}
return total;
}, [])
console.log(rel3);
arr3.sort(function (a, b) {
return a - b;
})
console.log(arr3);
day04
1构造函数继承
-
先定义一个父构造函数
-
再定义一个子构造函数
-
子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数
function Father(uname) {
// this 指向父构造函数的对象实例
this.uname = uname;
}
// 2 .子构造函数
function Son(uname, age) {
// this 指向子构造函数的对象实例
//3.使用call方式实现子继承父的属性
Father.call(this, uname);
this.age = age;
}
var son = new Son('小好', 18);
console.log(son);
2 原型对象继承方法
-
先定义一个父构造函数
-
再定义一个子构造函数
-
子构造函数继承父构造函数的属性(使用call方法)
// 1. 父构造函数
function Father(uname, age) {
// this 指向父构造函数的对象实例
this.uname = uname;
this.age = age;
}
Father.prototype.money = function() {
console.log(100000);
};
// 2 .子构造函数
function Son(uname, age, score) {
// this 指向子构造函数的对象实例
Father.call(this, uname, age);
this.score = score;
}
// Son.prototype = Father.prototype; 这样直接赋值会有问题,如果修改了子原型对象,父原型对象也会跟着一起变化
Son.prototype = new Father();
// 如果利用对象的形式修改了原型对象,别忘了利用constructor 指回原来的构造函数
Son.prototype.constructor = Son;
// 这个是子构造函数专门的方法
Son.prototype.exam = function() {
console.log('孩子要考试');
}
var son = new Son('小好', 18, 100);
console.log(son);
3.Object.create()
- 该方法用创建对象
- 第一个参数 是 以谁为原型创建新的对象
- 第二个参数 传入一个对象用来设置 新对象的值和属性特征
4.Object.create实现类式继承
Object.create(proto, [propertiesObject])
-
方法创建一个新对象,使用现有的对象来提供新创建的对象的
__proto__
。返回在指定原型对象上添加新属性后的对象。 -
proto:新创建对象的原型对象。
-
propertiesObject:可选。需要传入一个对象,该对象的属性类型参照
Object.defineProperties()
的第二个参数。如果该参数被指定且不为undefined
,该传入对象的自有可枚举属性(即其自身定义的属性,而不是其原型链上的枚举属性)将为新创建的对象添加指定的属性值和对应的属性描述符。
5.严格模式
什么是严格模式:
1.消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。
2.消除代码运行的一些不安全之处,保证代码运行的安全。
3.提高编译器效率,增加运行速度。
4.禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript 做好铺垫。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名
开启严格模式
<script>
"use strict"; //当前script标签开启了严格模式
</script>
<script>
//当前script标签未开启严格模式
</script>
严格模式的变化
- 严格模式后使用未声明的变量
- 严格模式不允许删除变量
- 严格模式下全局作用域中函数中的 this 是 undefined
- 严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
- 严格模式下,定时器 this 还是指向 window
- 严格模式下,函数里的参数不允许重名
'use strict'
num = 10
console.log(num)//严格模式后使用未声明的变量
--------------------------------------------------------------------------------
var num2 = 1;
delete num2;//严格模式不允许删除变量
--------------------------------------------------------------------------------
function fn() {
console.log(this); // 严格模式下全局作用域中函数中的 this 是 undefined
}
fn();
---------------------------------------------------------------------------------
function Person() {
this.sex = '男';
}
// Person();严格模式下,如果 构造函数不加new调用, this 指向的是undefined 如果给他赋值则 会报错.
var p1 = new Person();
console.log(p1.sex);
----------------------------------------------------------------------------------
setTimeout(function() {
console.log(this); //严格模式下,定时器 this 还是指向 window
}, 2000);
----------------------------------------------------------------------------------
// 严格模式下,函数里的参数不允许重名
function fun1(num, num) {
console.log(num + num);
};
fun1(2, 3);
6.高阶函数
高阶函数是对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出。符合以下条件其一:
-
参数是函数
-
函数作为返回值
7.闭包
函数嵌套函数 内部函数可以访问外部函数变量或参数 形成的此法环境叫做闭包
特性
函数套函数
内部函数可以访问外部函数的参数和变量
使变量长期驻扎在内存当中
优点
使变量长期驻扎在内存当中
内部函数可以访问外部函数的参数和变量
缺点
使用不当会造成内存泄露
8.递归
递归:如果一个函数在内部可以调用其本身,那么这个函数就是递归函数。简单理解:函数内部自己调用自己, 这个函数就是递归函数
注意:递归函数的作用和循环效果一样,由于递归很容易发生“栈溢出”错误(stack overflow),所以必须要加退出条件return。
求阶乘
function sum(num) {
if (num == 1) {
return 1;
} else {
return num * sum(num - 1);
}
}
var rel = sum(4);
console.log(rel);
9.抚平数组
// 多维转一维
var arr = [1, 2, 3, [4, 5, 6, [7, 8, 9, [10, 11, 12]]]]
// Array.isArray();
// var relarr = [];
function flatArr(data, relArr) {
// []
// [1]
// [1,2]
// [1,2,3]
relArr = relArr || [];
// console.log(relArr);
// 2.将多维数组进行遍历
data.forEach(function (v) {
// 3.判断当前元素如果是一个数组
if (Array.isArray(v)) {
// 4.利用递归 再次调用自己并将当前数组再次传入函数
flatArr(v, relArr);
} else {
// 5.如果当前元素不是数组 那么将添加到新数组内
relArr.push(v);
}
})
return relArr;
}
// 1.调用函数传入多维数组
var rel = flatArr(arr);
console.log(rel);
day05
1.浅拷贝
浅拷贝 : 赋值出来的对象与源对象共用同一个内存地址,存储在同一块空间
改变其中一个对象另一个也会改变
Object.assign(target,sources)
参数: target:目标对象。sources:源对象。
var obj = {
name: "哈哈哈",
age: 20,
gender: "🚹",
hobby: ["三国", "云边有个小卖部", "骆驼祥子"]
}
var obj2 = {
name: "啊啊啊",
sayHi: function () {
console.log("to day is 八月 last day");
}
}
var newobj = {};
Object.assign(newobj, obj, obj2);
console.log(newobj);
2 深拷贝
深拷贝:重新开辟一块空间用来存储新对象
与源对象不共用一块内存空间
深拷贝 使用JSON下面的两个方法
JSON.stringify()将对象转换为json字符串格式
JSON.parse() 将字符串转换为json对象格式
console.log(JSON.parse(JSON.stringify(obj)));
var obj = {
name: "哈哈哈",
age: 20,
gender: "🚹",
hobby: ["三国", "云边有个小卖部", "骆驼祥子", {
lookmovies: ["林正英", "漫威", "贞子", "釜山行", "生化危机"]
}]
}
var obj3 = JSON.parse(JSON.stringify(obj));
obj.hobby[0] = "红楼梦"
console.log(obj3);
3.类
创建类
//步骤1 使用class关键字
class Person {
// class body
}
//步骤2使用定义的类创建实例 注意new关键字
var xx = new Person();
class Person {
constructor(uname, age) {
this.uname = uname;
this.age = age;
}
}
// 2. 利用类创建对象 new
var p1 = new Person('张三', 18);
console.log(p1);
console.dir(Person);
4.类操作DOM元素
<style> .box { width: 100px; height: 100px; background-color: pink; float: left; margin-right: 20px; } </style> </head> <body> <div class="box">1</div> <div class="box">2</div> <div class="box">3</div> <div class="box">4</div> <script> class Dom { // 初始化属性 constructor(className) { this.box = document.querySelectorAll(className) console.log(this); this.init(); } // 用来初始化事件 init() { for (var i = 0; i < this.box.length; i++) { this.box[i].onclick = this.logEvent } } logEvent() { console.log(this); this.style.width = 300 + "px"; } } var p1 = new Dom('.box') console.log(p1); </script>
5.类的继承
extends关键字表示类的继承
子类使用super关键字访问父类的方法
class Father {
constructor(name, age, height) {
this.name = name;
this.age = age;
this.height = height;
}
makeMeony() {
console.log("疯狂赚钱");
}
}
// extends 继承
class Son extends Father {
constructor(name, age, height) {
// super 使用super 方法访问父类身上的属性
super(name, age, height)
}
makeMeony(){
console.log("儿子长大了 自己赚钱");
}
}
var father = new Father("小头爸爸", 50, 180);
var son = new Son("大头儿子", 31, 170);
console.log(father);
console.log(son);
son.makeMeony()