面向对象编程思想
1. 面向过程与面向对象区别
面向对象 | 面向过程 |
---|---|
易维护、易复用、易扩展 | 性能比面向对象高,适合跟硬件联系紧密 |
性能比面向过程低 | 不易维护 |
2. 对象与类
在ES6中增加了类的概念,可以使用 class 关键字声明一个类,之后以这个类来实例化对象。类抽象了对象的公共部分,它泛指某一大类(class)对象特指某一个,通过类实例化一个具体的对象
2.1 创建类
- 语法规范:
- 通过class 关键字创建类, 类名我们还是习惯性定义首字母大写
- 类里面有个constructor 函数,可以接受传递过来的参数,同时返回实例对象
- constructor 函数 只要 new 生成实例时,就会自动调用这个函数, 如果我们不写这个函数,类也会自动生成这个函数
- 多个函数方法之间不需要添加逗号分隔
- 生成实例 new 不能省略
- 语法规范, 创建类 类名后面不要加小括号,生成实例 类名后面加小括号, 构造函数不需要加function
<script>
//1.声明一个类
class Father{
//构造函数 实例化对象时自动会执行构造函数 可以用来传参
constructor(x,y){
this.name = x;
this.age = y;
}
sing(){
console.log("我是father");
}
}
//2.使用自定义类实例化一个对象
var father = new Father("name","age");
//3.调用
console.log(father.name); // 输出"name"
father.sing(); // 输出"我是father"
</script>
2.2 继承类
继承类使用关键字extends
<script>
//1.声明一个父类
class Father{
//构造函数 实例化对象时自动会执行构造函数 可以用来传参
constructor(x,y){
this.x = x;
this.y = y;
}
sum(){
console.log(this.x+this.y);
}
}
//2.继承父类
class Son extends Father{
contructor(x,y){ //参数传递2:接受参数
// 利用super 调用父类的构造函数 super 必须在子类this之前调用,放到this之后会报错
super(x,y); //参数传递3:调用父类构造函数 并传参
this.x = x;
this.y = y;
}
subtract(){
console.log(this.x-this.y); //调用 使用的是子类的x y
}
}
//3.使用自定义类实例化一个对象
var son = new Son(5,3); //参数传递1:实例化传给son类的构造函数
//4.调用
son.sum(); // 输出"8" 传参给son的构造函数 再通过super传参给父类的构造函数
son.subtract(); // 输出"2"
</script>
3. 构造函数与原型
3.1 创建对象的三种方式
<script>
// 1.字面量创建对象
var obj1 = {};
// 2.new关键字
var obj2 = new Object();
// 3.构造函数创建对象
function Star(name,age){
this.name = name;
this.age = age;
}
var obj3 = new Star("洪吉潮",18);
</script>
3.2 静态成员与实例成员
<script>
// 1.字面量创建对象
var obj1 = {};
// 2.new关键字
var obj2 = new Object();
// 3.构造函数创建对象
function Star(name,age){
this.name = name;
this.age = age;
}
var obj3 = new Star("洪吉潮",18);
// 4.访问
console.log(obj3.name); //实例成员只能通过实例化对象访问
Star.scale = 100; //在构造函数本身添加成员,为静态成员
console.log(Star.scale); //静态成员只能通过构造函数对象来访问
</script>
3.3 构造函数的问题
构造函数方法很好用,但是存在浪费内存的问题
3.4 构造函数原型对象prototype
<script>
//声明一个构造函数
//每一个object都有一个__proto__对象原型 指向Star的prototype
function Star(name,age){
this.name = name;
this.age = age;
}
//实例化对象
var obj = new Star('hjc',18);
//Star的prototype
Star.prototype.sing = function(){
console.log("我会唱歌");
}
console.log(obj);
obj.sing();
</script>
3.5 对象原型__proto__
- 构造函数都有一个prototype原型对象
- 实例化对象有一个__proto__对象原型
- __proto__对象原型指向构造函数的prototype
- 可以通过实例化对象访问构造函数Star的prototype的原型对象
3.6 constructor构造函数
- 每一个对象原型( _ proto _ )和原型对象(prototype)都有一个constructor属性
- constructor构造函数 指回函数的本身
<script>
// 1. 每一个对象原型( _ _proto_ _ )和原型对象(prototype)都有一个constructor属性
// 2. constructor构造函数 指回函数的本身
function Star(name,age){
this.name = name;
this.age = age;
}
//实例化对象
var obj = new Star('hjc',18);
console.log(Star.prototype.constructor);
console.log(obj.__proto__.constructor);
</script>
上述代码console输出结果
一般我们用这个constructor指回函数本身
<script>
// 1. 每一个对象原型( _ _proto_ _ )和原型对象(prototype)都有一个constructor属性
// 2. constructor构造函数 指回函数的本身
function Star(name,age){
this.name = name;
this.age = age;
}
Star.prototype = {
constructor:Star, // 利用constructor属性指回构造函数本身
sing:function(){console.log('我会唱歌');},
dance:function(){console.log('我会跳舞');}
}
//通过对象给prototype原型对象赋值,会把自带的constructor给去除
//实例化对象
var obj = new Star('hjc',18);
console.log(Star.prototype.constructor);
console.log(obj.__proto__.constructor);
</script>
3.7 原型链
每一个实例对象又有一个 _ proto _ 属性,指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有 _ proto _ 属性,这样一层一层往上找就形成了原型链。
3.8 构造函数实例和原型对象的三角关系
1.Star有一个原型对象prototype属性
2.Star原型对象prototype.constructor能指向构造函数本身
3.实例化对象有一个 _ _ proto _ _ 属性 指向 Star原型对象prototype
3.9 原型链和成员的查找机制
1.当访问一个对象的属性(包括方法)时,首先查找这个对象自身有没有该属性
2.如果没有就查找它的原型(也就是 __proto__指向的 prototype 原型对象)
3.如果它的原型没有找到该属性,就去这个原型的原型对象找该属性
4.直到原型对象最后返回一个null为止
3.10 原型对象中的this指向
构造函数中的this和原型对象的this,都指向我们new出来的实例对象
<script>
function Star(uname, age) {
this.uname = uname;
this.age = age;
}
var that;
Star.prototype.sing = function() {
console.log('我会唱歌');
that = this;
}
var ldh = new Star('刘德华', 18);
// 1. 在构造函数中,里面this指向的是对象实例 ldh
console.log(that === ldh);//true
// 2.原型对象函数里面的this 指向的是 实例对象 ldh
</script>
3.11通过原型为数组拓展内置对象
通过原型拓展内置对象
<script>
console.log(Array.prototype);
Array.prototype.sum = function(){
var sum = 0;
for(var i=0;i<this.length;i++){
sum += this[i];
}
return sum;
}
var arr = new Array(5,10,15,20);
console.log(arr.sum());
</script>
4. 继承
4.1 call()
- call()可以调用函数
- call()可以修改this的指向
<script>
function fn(x,y){
console.log(this);
console.log(x+y);
}
var o = {
name:"andy"
}
fn(5,10); //指向window的对象
fn.call(o,5,15); //指向o的对象
</script>
4.2 子构造函数继承父构造函数中的属性
<script>
function Star(name,age){
this.name = name;
this.age = age;
}
function Son(name,age,scale){
//使用call,继承父构造函数的Star.name属性
Star.call(this,name,age);
this.scale = scale;
}
var son = new Son('hjc',18,100);
console.log(son);
</script>
4.3 借用原型对象继承方法
<script>
function Star(name,age){
this.name = name;
this.age = age;
}
Star.prototype.sing = function(){
console.log('唱歌');
}
function Son(name,age,scale){
//使用call,继承父构造函数的Star.name属性
Star.call(this,name,age);
this.scale = scale;
}
//实例化star对象赋值给prototype 此时constructor是指向的是star的本身
Son.prototype = new Star();
//让constructor指向调用者son的本身
Son.prototype.constructor = Son;
var son = new Son('hjc',18,100);
console.log(son.__proto__.constructor);
son.sing();
</script>
5.0 ES5新增方法
5.1 forEach遍历数组
1.遍历数组,没有返回值
<script>
var arr = [{id:1,name:'111'},{id:2,name:'222'}];
arr.forEach(function(value,index,arr){
//value 当前数据的值
//index 当前数据的索引号
//arr 当前数组
//console.log(value);
//console.log(index);
//console.log(arr);
//console.log(value.id + " " + value.name);
})
</script>
5.2filter过滤数组
1.遍历数组,会返回新的数组
<script>
var arr = [{id:1,name:'111'},{id:2,name:'222'},{id:3,name:'333'},{id:4,name:'444'},{id:5,name:'555'}];
var newArr = arr.filter(function(value,index,arr){
//value 当前数据的值
//index 当前数据的索引号
//arr 当前数组
return value.id>3;
});
console.log(newArr);
</script>
5.3 some查找数组
<script>
var arr = [{id:1,name:'111'},{id:2,name:'222'},{id:3,name:'222'},{id:4,name:'444'},{id:5,name:'555'}];
var res = arr.some(function(value){
if(value.name === "222"){
return true; //当查找到222时,返回一个true,会终止本次迭代(遍历)
}
console.log(value);
});
console.log(res);
</script>
5.4 trim()方法 去除空白字符串
<script>
str.trim();
</script>
5.5 Object.keys() 获取对象自有属性
<script>
var obj = {
id:1,
name:'hjc',
scale:100,
age:18
}
Object.keys(obj); //返回所有属性名的数组
</script>
5.6 Object.defineProperty() 添加或修改对象中的属性
<script>
/*
Object.defineProperty(对象,修改或新增的属性名,{
value:修改或新增的属性的值,
writable:true/false,//如果值为false 不允许修改这个属性值
enumerable: false,//enumerable 如果值为false 则不允许遍历
configurable: false //configurable 如果为false 则不允许删除这个属性 属性是否可以被删除或是否可以再次修改特性
*/
})
</script>
<script>
var personObj = {
id:001,
name:'张三',
age:18
}
Object.defineProperty(personObj,'sex',{
value:'男',
enumerator:true,
writable:true. //设置为false,第十行的修改属性失效
})
personObj.sex = '女'; //第十行
console.log(personObj.sex);
</script>
本节新get知识点
<script>
1.insertAdjacentHTML()和 insertAdjacentText()
ele.insertAdjacentHTML(swhere,stext)
/*参数:
swhere: 指定插入html标签语句的地方,
stext:要插入的内容
有四种值可用:
1.beforeBegin: 插入到标签开始前
2.afterBegin:插入到标签开始标记之后
3.beforeEnd:插入到标签结束标记前
4.afterEnd:插入到标签结束标记后
*/
2.双击事件去除选中文本效果
window.getSelection ? window.getSelection().removeAllRanges() : document.selection.empty();
</script>