一、面向对象编程
1.程序是干什么的?
程序就是对现实世界的抽象(照片就是对人的抽象)
2.对象是干什么的 ?
(1)一个事物抽象到程序中后就变成了对象
(2)在程序的世界中,一切皆对象
例子:
var wcz={
//添加属性
name:"王城主",
age:18,
hobby:"扣脚",
//添加方法
"introduce":function(){return "我的名字叫"+this.name+",今年"+this.age+"岁,喜欢"+this.hobby}
};
二、面向对象三大特点
封装、继承、多态
三、继承
1.父对象的成员(属性和方法),子对象可以直接使用
为什么要继承?
代码 重用,节约内存空间
何时继承?
只要多个子对象公用的属性和方法,都要集中定义在父对象之中
2.js的面向对象是基于原型(爸爸)的
什么是原型?
保存一类子对象共有属性和方法的父对象(原型对象),每个对象天生就有一个原型
(1)获取原型对象:2种
● 对象名.__proto__;
必须先创建出一个对象,才可以使用此方法
var ccl = {
"name": "宁采臣",
"age": 300,
"gender": "女"
}
console.log(ccl);
console.log(ccl.__proto__);//直接找到原型对象
●构造函数名.prototype; —— 构造函数名:Array、Function、Date....
没有创建过任何对象也可以找到原型
<script>
console.log(Object.prototype);
</script>
<script>
console.log(Object.prototype); //对象爸爸
console.log(Array.prototype); //数组爸爸
console.log(Date.prototype); //日期爸爸
console.log(RegExp.prototype); //正则爸爸
</script>
(2)原型链:每个对象都有一个.__proto属性,可以不断的连续,找到爸爸-爷爷-祖祖...形成的一条链式结构
最顶层 :Object.prototype是对象的原型,万物皆对象
作用:查找属性和方法,自己没有的属性和方法顺着原型链查找,所以为什么人人都可以使用toString方法(除了undefined和null)。
(3)获取到原型对象则可以设置共有属性和共有方法
原型对象.属性名=属性值;——共有属性
原型对象.方法名=function(){};——共有方法
var ccl = {
"name": "宁采臣",
"age": 20,
"gender": "男"
}
var xq = {
"name": "聂小倩",
"age": 300,
"gender": "女"
}
ccl.__proto__.money = 1000000000; //不管是ccl还是xq都是对象,都是object,有一个共同的爸爸
// ccl.__proto__===Object.prototype
console.log(ccl); //本地没有money,原型有
console.log(ccl.money);
console.log(xq);
console.log(xq.money);
conslole.log(xq["ag"]);
<!DOCTYPE html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
/*
继承
- 可以通过extends关键来完成继承
- 当一个类继承另一个类时,就相当于将另一个类中的代码复制到了当前类中(简单理解)
- 继承发生时,被继承的类称为 父类(超类),继承的类称为 子类
- 通过继承可以减少重复的代码,并且可以在不修改一个类的前提对其进行扩展
封装 —— 安全性
继承 —— 扩展性
多态 —— 灵活性
*/
class Animal{
constructor(name){
this.name = name
}
sayHello(){
console.log("动物在叫~")
}
}
class Dog extends Animal{
}
class Cat extends Animal{
}
class Snake extends Animal{
}
const dog = new Dog("旺财")
const cat = new Cat("汤姆")
dog.sayHello()
cat.sayHello()
console.log(dog)
console.log(cat)
</script>
</head>
<body>
</body>
</html>
自有和共有:
自由:保存在对象本地的属性
共有:保存在父(原型)对象的属性,所有的子对象都可以使用
笔试题:
1、如何判断自有和共有
判断自有:obj.hasOwnProperty("属性名');
返回一个布尔值:true说明是自有,false可能是共有也可能是自有
var wsc = {
"name": "王思聪",
"dog": "阿拉斯加",
"gf": "很多"
}
wsc.__proto__.money = 10000000000000;
console.log(wsc.hasOwnProperty("name")) //true
console.log(wsc.hasOwnProperty("dog")) //true
console.log(wsc.hasOwnProperty("gf")) //true
console.log(wsc.hasOwnProperty("money")) //false(本地没有,父亲有)
console.log(wsc.hasOwnProperty("phone")) //false
//完整版:
if(obj.hasOwnProperty("属性名")){
console.log("自有");
}else{
if("属性名" in 对象名){
console.log("共有")
}else{
console.log("没有")
}
}
2、修改或删除属性
(1)修改和删除自有属性
修改:obj.属性名=新值;
删除:delete obj.属性名;
(2)修改和删除共有属性
修改:原型对象.属性名=新值;
删除:delete 原型对象.属性名;
3、为老IE的数组添加indexOf方法 - 这道题不是固定的:为某一类人设置一个方法
if(Array.prototype.indexOf===undefined){//我不希望主流浏览器也执行到这些代码,我只希望老IE执行到
Array.prototype.indexOf=function(key,starti){//indexOf的执行原理
starti===undefined&&(starti=0);//说明用户没有传入开始位置,我们就给用户设置为从下标0开始查找
for(var i=starti;i<this.length;i++){//从开始位置处,循环数组后面的每一个文字和用户输入的关键字进行匹配
if(this[i]==key){
return i;//匹配到了返回对应的下标
}
}
//没匹配到,返回-1
return -1;
}
}
4、判断x是不是数组?4种方法
(1)判断x是不是继承自Array.prototype
Array.prototype.isPrototypeOf(x);
如果返回true,说明是数组,否则不是数组
(2)判断x是否是由构造函数Array创建的
x instanceof Array
(3)ES5提供了一个API:Array.isArray(x); - 此方法不是人人都有,而且ES5以上的东西,老IE都不支持(别怕,现在的开发流行趋势,不是PC端,而是移动端,IOS(safari)和andriod(chrome))
(4)输出对象的字符串形式:
在Object的prototype原型上放着最原始的toString
原始的toString,默认输出[object 构造函数名]
***多态(override)/重写:子对象绝对父对象的成员不好用,可以在本地定义同名成员,覆盖父对象之中的成员
不专业的理解:同一个函数,不同的人来使用,效果是不同的,其实根本不是同一个函数
我希望借用到函数:跳过爸爸,直接去找爷爷拿toString
Object.prototype.toString.apply(x)==="[object Array]";
5、实现自定义继承:
(1)实现两个对象之间的继承
子对象.__proto__=父对象;
(2)直接匹配设置继承
构造函数名.prototype=父对象;
时机:先设置好父对象,再创建子对象
面试题:简单的说一下你了解的面向过程和面向对象开发方式的区别?
面向过程:开始->经过->结束,我们从开始到现在学习写法的一直都是面向过程
面对象:对象(属性和方法),如果这个世界有各种属性和各种方法,但是连一个对象/生物都没有,那这些东西就没有具体的意义
我们把所有的代码全部包含在一个对象中来进行描写,才更符合现实生活
(3)铁索连舟,一个方法触发,多个方法联动 ,更符合现实生活
何时继承:只要多个子对象公用的属性和方法,都要集中定义在父对象之中
什么是原型:保存一类子对象共有属性和共有方法的父对象(原型对象),每个对象天生就有一个原型
var ccl = {
"name": "宁采臣",
"age": 300,
"gender": "女"
}
console.log(ccl);
"name": "宁采臣",
"age": 300,
"gender": "女"
}
console.log(ccl);
console.log(ccl.__proto__);//直接找到原型对象
构造函数名:Array、Function、Date、RegExp...
console.log(Object.prototype); //对象爸爸
console.log(Array.prototype); //数组爸爸
console.log(Date.prototype); //日期爸爸
console.log(RegExp.prototype); //正则爸爸
作用域链:以函数EC的scope chain属性为起点,经过AO逐级引用,形成的一条链式结构。作用:查找变量的,带来了变量的使用规则——优先使用自己的,自己没有找全局,全局没有则报错
原型链:每个对象都有一个.__proto__的属性,可以不断的连续.找到爸爸-爷爷-祖祖...形成的一条链式结构
最顶层:Object.prototype是对象的原型,万物皆对象
作用:查找属性和方法,自己没有的属性和方法,可以自动顺着原型链进行查找,所以人人都可以使用toString(除了undefined和null)
"name": "宁采臣",
"age": 20,
"gender": "男"
}
var xq = {
"name": "聂小倩",
"age": 300,
"gender": "女"
}
ccl.__proto__.money = 1000000000; //不管是ccl还是xq都是对象,都是object,有一个共同的爸爸
// ccl.__proto__===Object.prototype
console.log(ccl); //本地没有money,原型有
console.log(ccl.money);
console.log(xq);
console.log(xq.money);
conslole.log(xq["ag"]);
判断自有:obj.hasOwnProperty("属性名');
返回一个布尔值:true说明是自有,false可能是共有也可能是自有
"name": "王思聪",
"dog": "阿拉斯加",
"gf": "很多"
}
wsc.__proto__.money = 10000000000000;
console.log(wsc.hasOwnProperty("name")) //true
console.log(wsc.hasOwnProperty("dog")) //true
console.log(wsc.hasOwnProperty("gf")) //true
console.log(wsc.hasOwnProperty("money")) //false(本地没有,父亲有)
console.log(wsc.hasOwnProperty("phone")) //false