js面向对象知识点

it2022-05-09  31

js面向对象知识点

文章目录

js面向对象知识点1. 对象的定义2. js的对象分类3. typeof 与 instanceof 的应用3.1 typeof3.2 instanceof3.3 示例 4. 属性的操作4.1 访问某个属性4.2 给对象添加属性4.3 获取全部可以枚举的实例属性 5. 利用属性的特性,完成例子5.1 数组去重5.2 统计数组中个元素出现次数 6. 原型与原型链6.1 原型6.2 原型链 7. this 的应用7.1 如何确定this的值7.2 this 的总结7.3 call,apply与bind可以改变this的指向 8. 创建对象的N种方式8.1 字面量方式8.2 工厂模式8.3 构造器模式(使用new)8.4 构造器 + 原型 模式 9. 继承9.1 原型继承9.2 继承的浅拷贝9.3 继承的深拷贝 10 class的应用10.1 使用css创建对象10.2 使用extends实现继承

1. 对象的定义

对象 是无序属性的集合

2. js的对象分类

内置对象

本地对象 Object、Array、String、Number、Boolean、Date、Error… 单体内置对象 只有 Global 和 Math 两者的区别: 单体对象不需要加new

宿主对象

js寄宿环境定义的对象, eg:window、document、history

自定义对象

3. typeof 与 instanceof 的应用

3.1 typeof

typeof 输出数据所属的类型

格式:

typeof 数据

3.2 instanceof

格式 要判断的数据 instanceof 类型 功能 查看数据是否是指定的类型

3.3 示例

4. 属性的操作

4.1 访问某个属性

方式一:对象名.属性

obj.name

方式二:对象名[属性]。

obj["name"];

注意:如果属性名被保存在某一个变量,只能使用第二种方式。

4.2 给对象添加属性

两种方式

对象名.属性名 = 属性值;

obj.mame = "zhangsan"

对象名[“属性名”] = 属性值;

obg["name"] = "zhangsan"

属性有四个特征

configurable:是否可以删除。默认为true。writable:是否可以修改属性的值。默认为true。enumerable:是否可以修改属性的值。默认为true。value:值。默认为undefined

精细设置对象的属性

格式

Object.defineProperty(对象名,“属性名”,{ Configurable: Writable: Enumerable: Value: })

示例:

案例:设置一个只读属性,模拟常量

4.3 获取全部可以枚举的实例属性

Object.keys();

5. 利用属性的特性,完成例子

5.1 数组去重

let arr = [1,1,2,2,3,3]; let newArr = []; let obj = {}; for(i=0;i<arr.length;i++){ let t = arr[i]; if(obj[t]){ }else{ obj[t] = true; newArr.push(t); } } console.log('newArr :', newArr);

输出结果:

5.2 统计数组中个元素出现次数

let arr = [1,1,2,2,3,3]; let obj = {}; for(i=0;i<arr.length;i++){ let t = arr[i]; if(obj.hasOwnProperty(t)){ obj[t] += 1; }else{ obj[t] = 1; } } console.log('obj :', obj);

输出结果:

6. 原型与原型链

6.1 原型

prototype 就是原型 每一个函数都有一个prototype属性函数的原型是一个对象,原型里面与很多方法,但是一定有constructor方法constructor指向这个函数本身

proto 隐式原型,它对外是隐藏的,我们在程序开发过程,不会直接使用它。 每一个对象都有一个__proto__属性对于函数而言,每一个函数都会有一个prototype和一个__proto__属性。

结论:

对象的__proto__属性 指向 创建这个对象的函数的prototype

6.2 原型链

原型链 访问一个对象的属性时,先在这个对象自己的属性中去找,如果找不到,则沿着__proto__这个属性向中找,如果__proto__这个对象中还是没有找到,就在__proto__对象的__proto__属性中去找,依次下去,这就是原型链。

注意:

由于对象的__proto__[隐式原型]与创建这个对象的函数(构造器)的prototype是一致的。所以理论上,你对__proto__修改会直接影响prototype。建议只使用prototype[原型]

7. this 的应用

7.1 如何确定this的值

答:谁调用了this就是谁。

看方法前的那个对象是谁,this就指向谁。

(1)有明确的对象

例如:Obj.say();say 的当前对象是obj,所以say中的this 就指向obj。

(2)没有明确的对象

如果这个函数没有明确说是哪个对象的,则它肯定是属于window对象的,所以this就会指向window.

(3)如果是call和apply的方式,这时,this指向第一个参数

例如:f.call(obj1),f中的this指向obj1。

7.2 this 的总结

this出现在全局中,this是windowthis出现在一个普通的函数中(不是方法),this是windowthis出现在一个对象的方法,this可以是这个对象,也可以是windowcall和apply可以改变this指向,指向()第一个参数一个函数没有明确指出谁调了,this是window

7.3 call,apply与bind可以改变this的指向

请参考

call,apply与bind的应用

8. 创建对象的N种方式

8.1 字面量方式

例子:矩形对象

优点:直接了当,yimuliao缺点:不能批量生产对象,只能一个一个写

8.2 工厂模式

例子:

// 利用工厂模式创建对象 工厂利用一个函数来模拟 function factory(w,h){ // 批量地产生矩形对象 let obj = {} obj.width = w; obj.height = h; obj.getC = function(){ return (this.width+this.height)*2 } obj.getS = function(){ return this.width*this.height } return obj; } let r1 = factory(1,2) let r2 = factory(2,3) console.log(r1.getC()) // 6 console.log(r1.getS()) // 2 console.log(r2.getC()) // 10 console.log(r2.getS()) // 6

优点:主要解决了字面量方式的不能批量生产对象的问题。

缺点:他产生的对象没有“商标”(不知道是谁生产的)

8.3 构造器模式(使用new)

示例:

new做了如下四件事:

创建一个对象 var o = {};

F.call(o); // 先执行F()函数,同时把this用o来代替。把F()构造器设置的各种属性值,直接赋给o. 理解如下代码:

o.proto = F.prototype //让o具备F.prototype上定义的方法。

return o;


构造器模式优点:

解决了对象的来源不明的问题。我们可以通过对象的constructor属性,找到它的构造器。new 构造器() 这种格式会受面向对象的程序员(java,C#,C++…)所接受。具备工厂模式的批量生产(还可以是定制的,例如传参不同) 。

构造器模式缺点:不能像数组一组,共用方法。内存浪费。

8.4 构造器 + 原型 模式

function Rect(w, h) { this.width = w; this.height = h; } Rect.prototype.getC = function(){ return (this.width+this.height)*2 } Rect.prototype.getS = function(){ return this.width*this.height } // r1 r2 r3都有getC和getS 造成内存空间的浪费 let r1 = new Rect(1, 2); let r2 = new Rect(2, 3); console.log(r1.getC()) // 6 console.log(r1.getS()) // 2 console.log(r2.getC()) // 10 console.log(r2.getS()) // 6

9. 继承

9.1 原型继承

function Parent(yourname) { this.name = yourname; } Parent.prototype.say = function () { console.log(this.name) } // 让Son去继承name属性和say方法 function Son(yourname) { // 继承属性 Parent.call(this,yourname) } // 继承方法 Son.prototype = Parent.prototype; Son.prototype.constructor = Son; //调用 let s = new Son("hrllo"); s.say();

9.2 继承的浅拷贝

浅拷贝 将父类的原型对象直接复制给子类的原型对象 Son.prototype = Parent.prototype; Son.prototype.constructor = Son;

若有多个对象,多个对象指向同一个原型对象,parent,肯能存在干扰

9.3 继承的深拷贝

深拷贝 把原型对象copy一份 让Son继承copy过来的 for(let i in Parent.prototype){ Son.prototype[i] = Parent.prototype[i] }

每个对象各自独立,不存在干扰的现象

10 class的应用

10.1 使用css创建对象

格式:

class 类名{ constructor(参数){ this.属性= 参数; } method(){//对象中简写方法,省略了function。不要与箭头函数搞混了。 } }

注意:

class是关键字,后面紧跟类名,类名首字母大写,采取的是大驼峰命名法则。类名之后是{}。在{}中,不能直接写语句,只能写方法,方法不需要使用关键字方法和方法之间没有逗号。不是键值对。 例子: [外链图片转存失败(img-TAXlJqlA-1563964992735)(https://gitee.com/qyd_9/nodebook_image/raw/master/小书匠/201972403-js的面向对象724968d776daf62acfb0c2ac6d2d84e7724-4.png)]

调用方式:

10.2 使用extends实现继承

格式:

class 子类 extends 父类{ constructor(参数){ super(参数) this.属性 = 值 } }

注意:

使用extends关键字来实现继承在子类中的构造器constructor中,必须要显式调用父类的super方法,如果不调用,则this不可用

示例:

class NBAPlayer { constructor(name, age, height) { this.name = name this.age = age this.height = height } say() { console.log(`我是${this.name},今年${this.age},我的身高是${this.height}`) } jump() { console.log("jump...") } } class MVP extends NBAPlayer { constructor(name, age, height, year) { super(name, age, height) this.year = year; } showMVP() { console.log(`我是${this.name},我是${this.year}年的MVP`) } } var m1 = new MVP("xiaoqiang","33","191",2010) m1.say() m1.showMVP()

最新回复(0)