1.面向对象
面向过程:POP:分析解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用时再一个一个的依次调用。 Process-oriented programming
面向对象:oop:事物分解成一个个对象,然后由对象之间分工合作 object Oriented Programming
特性:封装性,继承性,多态性
对象:js中一组无序的相关属性和方法的集合,所有事物都是对象
对象由属性和方法组成。
属性:事物的特征,常用名词
方法:事物的行为,常用动词
类:es6新增的,class关键字声明一个类,通过类来实例化对象。
类抽象了对象的公共部分,泛指的某一大类。
1.1 创建类
class Star {
constructor(uname){
this.uname = uname;
}
sing(song){
console.log(this.uname + song);
}
}
var yy = new Star('杨洋');
yy.sing('安心的温柔');
1.2 继承
class Father{
constructor(x,y){
this.x = x;
this.y = y;
}
money(){
console.log('100');
}
sum(){
console.log(this.x + this.y);
}
}
class Sum extends Father {
constructor(x,y){
// 先继承父类,再使用子类的
super(x,y);// 调用了父类的构造函数
this.x = x;
this.y = y;
}
subtract(){
console.log(this.x - this.y);
}
}
var son new Son(1,2);
son.sum();
注意点:1.es6中没有变量提升,必须先定义再使用
2.类里面的共有的属性和方法一定要加this使用
3.this的指向问题
constructor:this -- 创建的实例对象
方法: this -- 谁调用指向谁
2.构造函数和原型
- 首字母要大写
- 使用new关键字创建对象
- 存在内存的浪费问题
function Star(uname,age){
this.uname = uname;
this.age = age;
this.sing = function (){
console.log('我会唱歌');
}
}
var yy = new Star('杨洋');
// 实例成员:构造函数内部通过this添加的成员 只能通过实例化对象访问
//this.uname = uname;
// 不能通过构造函数来访问实例成员
console.log(yy.uname);
// 静态成员:在构造函数本身上添加的成员
Star.sex = '男';
// 静态函数只能通过构造函数访问
console.log(Star.sex);
构造函数原型prototype:每一个构造函数都有一个prototype这个对象
可以把一些不变的方法直接定义到prototype对象上,对象的实例化方法都可以共享。
function Star(uname,age){
this.uname = uname;
this.age = age;
}
// 一般情况下,我们公共的属性定义构造函数里面,公共的方法放到原型上。
/*Star.prototype.sing = function(){
console.log('我会唱歌');
}*/
Star.prototype = {
// 指回原来的构造函数
constructor: Star,
sing:function(){
console.log('我会唱歌');
},
movie:function(){
console.log('我会演电影');
}
}
var yy = new Star('杨洋');
对象原型 proto:构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有proto原型的存在。
因为proto的存在,就会去构造函数的原型上查找,
proto对象原型和原型对象prototype是等价的。
proto和构造函数的原型对象prototype里面都有一个constructor属性-- 指向构造函数本身。
原型链:
- 只有构造函数,就有proto指向原型对象。
- 构造函数的原型对象的 proto指向Object的prototype
- Objec的proto指向 null.
this指向:
- 构造函数中的this指向 --- 对象实例
- 构造函数的原型对象中的函数中this指向 --- 对象实例
通过原型对象可以扩展内置对象:
Array.prototype.sum = function(){
var sum = 0;
for(var i=0;i<this.length;i++){
sum += this[i];
}
return sum;
}
var arr = [1,2,3];
arr.sum();
1.4 继承
call :可以改变this指向 可以调用函数
// 借用父构造函数继承属性
function Father(uname,age){
this.uname = uname;
thi.age = age;
}
// 借用构造函数实现继承不能继承方法
Father.prototype.money = function(){
console.log('100000');
}
function Son(uname,age,score){
Father.call(this,uname,age);
this.score = score;
}
var son = new Son('慕寒',18,100);
console.log(son);
// 借用原型对象继承方法
function Father(uname,age){
this.uname = uname;
thi.age = age;
}
// 借用构造函数实现继承不能继承方法
Father.prototype.money = function(){
console.log('100000');
}
function Son(uname,age,score){
Father.call(this,uname,age);
this.score = score;
}
// 修改了父原型对象 - 修改子原型对象 父的也会修改
// Son.prototype = Father.prototye;
// 如果利用对象的方式修改了原型对象,不忘用constructor指回原来的构造函数
Son.prototype = new Father();
Son.prototype.constructor = Son;
Son.prototype.exam = function(){
console.log('孩子要考试')
}
var son = new Son('慕寒',18,100);
console.log(son);
1.5 es5新增的方法
数组方法:
//forEach 迭代数组 遍历数组
// map
var arr = [1,4,5,6];
var sum = 0;
arr.forEach(function(value,index,array){
console.log('每一个数组元素:',value);
console.log('每一个数组索引号:',index);
console.log('数组元素本身:',array);
sum += value;
});
// filter 筛选数组 返回一个新数组 返回所有满足条件的元素
var arr = [12,55,67];
var newArr = arr.filter(function(value,index,array){
return value >= 20;
});
console.log(newArr);
// some 返回值是布尔值 查找数组中是否有满足条件的元素存在 如果查找到第一个满足条件的元素就终止循环。
// every
var arr = [13,58,56,60];
var flag = arr.some(function(value,index,array){
return value > 20;
});
console.log(flag);
字符串方法
// trim 去掉字符串两端的空格 返回一个新的字符串
var str = ' andy ';
var str1 = str.trim();
对象方法
// Object.keys(obj); 获取对象自身的所有属性 返回由属性名组成的数组
var obj = {
id:1,
pname:'苹果',
price: 4.55
};
var arr = Object.keys(obj);
console.log(arr); // ["id","pname","price"];
// Object.defineProperty 定义对象的新属性或者修改原来的属性
// 参数:obj, prop[属性],descriptor[描述]
// 添加一条属性 num:1000
Object.defineProperty(obj,'num',{
value:1000
});
// 修改 价格为5
Object.defineProperty(obj,'price',{
value:5
});
// 限定id不能被重写
Object.defineProperty(obj,'id',{
// 值为false 不允许修改 默认值是false
writable: false,
// 是否可以枚举
enumrable:false,
// 是否可以被删除或重新设置
configurable: false
})
3. 函数进阶
函数的定义和调用
函数声明的方式 命名函数
函数表达式 匿名函数
-
new Function 参数是字符串的格式
// var f = new Function('console.log(123)'); var f = new Function('a','b','console.log(a+b)'); f(1,2);
所有函数都是Function的实例 函数也是对象
函数的调用方式:
- 普通函数 函数名() this ---> window
- 对象的方法 对象.方法(); this ---> 指向调用者
- 构造函数 new this ---> 指向创建出来的实例
- 原型对象的this ---> 指向创建出来的实例
- 绑定事件的函数 触发相应事件调用 this ---> 指向触发事件的对象
- 定时器函数 定时器每个一定的调用 this ---> window
- 立即函数 自动调用 (function () {})() this ---> window
改变函数内部的this指向:
call: fn.call(this,can1,can2) 继承
-
apply:fn.apply(this,[can1,can2]); 利用apply借助数学内置对象求最大值最小值 数组
var arr = [1,2,3,4,56,78]; var max = Math.max.apply(null,arr); var min = Math.min.apply(null,arr);
bind fn.bind(this,can1,can2) 返回原函数的拷贝 不会调用原函数
不需要立即调用,但又需要改变this指向
var o = {
name: 'andy'
};
function fn(){
console.log(this);
}
var f = fn.bind(o);
this
严格模式
(function(){
// 开启严格模式
'use strict';
})
// 在严格模式,全局作用域 函数的this指向 undefined
// 严格模式,如果构造函数不加new创建 this指向 undefined
// 定时器中的this --- window
// 事件,对象还是指向调用者
高阶函数
对其他函数进行操作的函数,它接收函数作为参数或将函数作为返回值输出
jquery中动画执行完毕后调用的函数就是 高阶函数
闭包
变量作用域:
闭包:有权访问另一个函数作用域中变量的函数
作用:延伸了变量的作用范围
function fn(){
var num = 10;
return function() {
console.log(num);
}
}
fn(); // num = 10;
for(var i =0;i<lis.length;i++){
// 小闭包
(function (i){
lis[i].onclick = function(){
console.log(i);
}
})();
}
递归
递归:函数内部自己调用自己
var num = 1;
function fn(){
console.log('打印6句话');
if(num == 6){
return;
}
num++;
fn();
}
// 递归求阶乘
function fn(n){
if(n == 1){
return 1;
}
return n * fn(n-1);
}
fn();
// 斐波那契数列的第n项
// 1 1 2 3 5 8 13 21
function fb(n){
if(n === 1 || n === 2){
return 1;
}
return fb(n-1) + fb(n-2);
}
// 函数递归完成深拷贝
function deepCopy(newObj,oldObj){
for(var k in oldObj){
// 判断属性值是哪种数据类型
var item = oldObj[k];
// 是否为数组
if(item instanceof Array){
newObj[k] = [];
deepCopy(newObj[k],item);
}else if(item instanceof Object){
//是否为对象
newObj[k] = {};
deepCopy(newObj[k],item);
}else {
// 简单数据类型
newObj[k] = item;
}
}
}
4.正则表达式
正则表达式:匹配字符串中字符组合的模式 对象形式存在
特点:1.灵活性,逻辑性和功能性非常强
2.可以迅速地用极简单的方式达到字符串的复杂控制
3.对于刚接触的人来说,比较晦涩难懂
// 创建正则表达式
// 利用 RegExp对象
var reg = new RegExp(/123/);
// 字面量
var reg = /123/;
//检测是否符合正则表达式规范
reg.test(123);
元字符:
边界符:
边界符 | 演示 | 说明 |
---|---|---|
^ | /^abc/ | 必须写abc开头 |
$ | /abc$/ | 必须以abc结尾 |
() | /(abc){3}/ | 让abc重复3次 |
字符类:
字符流 | 演示 | 说明 |
---|---|---|
[] | /[abc]/ | 只有包含a或者b或者c都返回true |
[-] | [a-z] | 26个大写英文字母任何一个 |
[-] | [^A-Za-z$] | 英文字母中任意一个 |
量词符:设定某个模式出现的次数
量词符 | 演示 | 说明 |
---|---|---|
* | /^a*$/ | 可以出现0次和n次 |
+ | /^a+$/ | 可以出现1次和n+1次 |
? | /^a?$/ | 可以出现0次或1次 |
{3} | /^a{3}$/ | 重复3次 |
{3,} | /^a{3,}$/ | 重复3次及以上 |
{3,16} | /^a{3,16}$/ | 重复3-16次 |
预定义类:
预定义类 | 说明 |
---|---|
\d | 匹配0-9之前的数字 类似[0-9] |
\D | 匹配所有0-9以外的字符 类似[^0-9] |
\w | 匹配任意字母数字下划线 [A-Za-z0-9_] |
\W | 除字母数字下划线以外的字符 [^A-Za-z0-9_] |
\s | 匹配空格(换行符,制表符,空格符) [\t\r\n\v\f] |
\S | 匹配非空格字符 |
正则表达式的替换:replace
var str = 'andyred';
str.replace('andy','bady');
str.replace('/andy/','bady');
// 过滤敏感词
// 只能替换一个
str.replace('/激情/','**');
// g 全局 i 忽略大小写
str.replace('/激情/g','**');
5.es6
ES:EcmaScript 脚本语言的标准化规范
let const
let : 具有块级作用域 --- {} 产生的作用域
可以防止循环变量变成全局变量
不存在变量提升,必须先声明再使用
存在暂时性死区,变量会和块级作用域绑定,不会向上级作用域中查找
let a = 10;
{
let b = 20;
}
console.log(b); // 访问不到b,报错
const:声明常量 值(内存地址)不能变化的量
具有块级作用域
声明时必须赋初始值,否则会报错
常量赋值后,值不能修改。 -- 基本数据
常量赋值后,不能改变内存地址 --- 复杂数据类型
存储的数据不需要变化,尽量使用const定义变量
const PI = 3.14;
const arr = [100,200];
arr[0] = 'a'; // 可以改
const arr = ['a','b']; // 不能更改,报错
解构赋值
数组解构:一一对应
let [a,b,c] = [1,2,3];
console.log(b);
对象的解构:
let person = {
name: '慕寒',
age:30,
sex: '男'
};
let {name:myName,age,sex} = person;
console.log(myName);
箭头函数
如果函数体中一句代码,可以省略{}
如果形参只有一个,()可以省略
箭头函数不绑定this,没有this,箭头函数定义在哪,this就指向哪
let arr = () = >{
console.log(123);
}
res = (n1,n2) => n1 + n2;
剩余参数
将一个不定量的参数放在一个数组中
const sum = (...args) => {
let total = 0;
args.forEach(item => total += item);
return total;
}
// 匹配结构赋值使用
let arr1 = ['张三','李四','王五'];
let [s1,...s2] = arr1;
扩展运算符
let arr = [1,2,3];
// ...arr;
console.log(...arr); // 1,2,3
// 用于合并数组
let arr1 = [1,2,3];
let arr2 = [3,4,5];
// 方法1:
let arr3 = [...arr1,...arr2];
// 方法2:
arr1.push(...arr2);
// 可以将伪数组转换为真正的数组
let divs = document.querySeletor('div');
var arr = [...divs];
console.log(arr);
arr.push('a');
// Array.from() 将伪数组转换为真数组
var arr Array.from(divs,item => item * 2);
// find 查找第一个满足条件的值
let arr = [{
id:1,
name: '慕寒'
},{
id:2,
name: 'Vk'
}];
let res = arr.find(item => item.id == 2);
console.log(res);
// findIndex 找出第一个符合条件的索引
var arr = [10,20,50];
let res = arr.findIndex(item => item > 15);
console.log(res); // 1
// includes 某个数组是否包含给定的值 返回布尔值
let arr = ['a','b','c'];
arr.includes('a'); // true;
arr.includes('w'); // false
// 模板字符串
// 可以解析变量
// 可以换行
// 可以调用函数 直接显示函数的返回值
let name = '慕寒';
let sayHello = `hello,my name is ${name}`;
console.log(sayHello);
let res = {
name: '慕寒',
age: 18
};
let html = `<div>
<span>${res.name}</span>
<span>${res.age}</span>
</div>`;
// startsWith endsWith 以什么开头 以什么结尾
let str = 'asrfe';
console.log(str.startWith('as')); // true;
console.log(str.endsWith('fe'));
// repeat 将原字符重复
'x'.repeat(3); // 将x重复3次
Set数据结构
不会存储重复的值,其他和数组一样
const s1 = new Set(['a','b','c']);
console.log(s1.size); // 3
s1.add('d').add('e'); // 添加
s1.delete('a'); // 删除
s1.has('a'); // 判断某个值是否为s1的成员
s1.clear(); // 清空
// 遍历
s1.forEach(value => {
console.log(value)
});s
// 数组去重
let s2 = new Set(['a','b','a','c']);
console.log(s2); // 3
let arr = ...s2;