
正文
js学习之面向对象
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
一、创建对象的方法
1、 {} 字面量创建
var person ={
name: "lisi",
age: ,
say: function(){
alert(this.name);
}
};
2、 new Object()
var person = new Object();
person.name = "lisi";
person.age = ;
person.family = ["lida","lier","wangwu"];
person.say = function(){
alert(this.name);
}
3: 用构造函数创建
function Person(name,age,family) {
this.name = name;
this.age = age;
this.family = family;
this.say = function(){
alert(this.name);
}
}
var person1 = new Person("lisi",,["lida","lier","wangwu"]);
var person2 = new Person("lisi",,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person); //trueconsole.log(person1.constructor); //constructor 属性返回对创建此对象的数组、函数的引用
4:Object.create方法创建
创建完的对象有2个特点
1、 可以添加属性 (属性的值为非函数的任意数据类型)
2、 添加方法
const person = {
isHuman: false,
say: function () {
console.log(`My name is ${this.name}. Am I human? ${this.isHuman}`);
}
};const me = Object.create(person); //使用现有的对象来提供新创建的对象的__proto__
5、工厂模式
function createPerson(name,age,family) {
var o = new Object();
o.name = name;
o.age = age;
o.family = family;
o.say = function(){
alert(this.name);
}
return o;
}var person1 = createPerson("lisi",,["lida","lier","wangwu"]); //instanceof无法判断它是谁的实例,只能判断他是对象,构造函数都可以判断出
var person2 = createPerson("wangwu",,["lida","lier","lisi"]);console.log(person1 instanceof Object); //true
6、原型模式
function Person() {}Person.prototype.name = "lisi";
Person.prototype.age = ;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
alert(this.name);
};
console.log(Person.prototype); //Object{name: 'lisi', age: 21, family: Array[3]}var person1 = new Person(); //创建一个实例person1
console.log(person1.name); //lisivar person2 = new Person(); //创建实例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];P9
console.log(person2); //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name); //报错
console.log(person2.age); //
7、混合模式(构造函数模式+原型模式)
构造函数模式用于定义实例属性,原型模式用于定义方法和共享的属性
function Person(name,age,family){
this.name = name;
this.age = age;
this.family = family;
}Person.prototype = {
constructor: Person, //每个函数都有prototype属性,指向该函数原型对象,原型对象都有constructor属性,这是一个指向prototype属性所在函数的指针
say: function(){
alert(this.name);
}
}var person1 = new Person("lisi",,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",,["lida","lier","lisi"]);
console.log(person2);
new的工作原理
通过new创建对象经历4个步骤
1、创建一个新对象;[var o = {};] //创建一个空对象obj,然后把这个空对象的__proto__设置为Person.prototype(即构造函数的prototype);
2、将构造函数的作用域赋给新对象 (因此this指向了这个新对象);[Person.apply(o)] [Person原来的this指向的是window]
3、执行构造函数中的代码(为这个新对象添加属性);
4、返回新对象。
什么是面向对象编程(OOP)?
面向过程与面向对象
1)面向过程:面向过程专注于如何去解决一个问题的过程步骤。编程特点是由一个个函数去实现每一步的过程步骤,没有类和对象的概念。
2)面向对象:专注于由哪一个对象来解决这个问题,编程特点是出现了一个类,从类中拿到对象,由这个对象去解决具体问题。 对于调用者来说,面向过程需要调用者自己去实现各种函数。而面向对象,只需要告诉调用者,对象中具体方法的功能,而不需要调用者了解方法中的实现细节。
面向对象的三大特征
面向对象的三大特征是继承、封装、多态。JS可以模拟实现继承和封装,但是无法模拟实现多态,所以我们说JS是一门基于对象的语言,而非是面向对象的语言。
封装:封装就是指利用抽象数据类型将数据和基于数据的操作封装在一起,数据被保护在抽象类型的内部,系统的其他部分只有通过包裹在数据外面的被授权的操作,才能够与这个抽象数据类型交流与交互!
继承:继承实际上是存在于面向对象程序中的两个类之间的关系。当一个类拥有另一个类的所有数据和操作时,就称这两个类之间具有继承关系!
多态:多态是指一个程序中同名的不同方法共存的情况。面向对象的程序中多态的情况有多种,可以通过子类对父类方法的覆盖实现多态,也可以利用重载在同一个类中定义多个同名的不同方法!
1、封装
什么是Js封装,就是当你需要隐藏一些属性和方法是,就可以将这些属性和方法封装起来,然后通过一个外部可以调用的特定接口(也可以说是一个公共的方法)进行调用。
2、继承
原型,原型链
3、多态
多态是指一个程序中同名的不同方法共存的情况。
function Person(name, age, sex) {
this.name = name; //共有变量
var age = age; //私有变量
var sex = sex; //私有变量
this.show = function () {
console.log(age + "====" + sex);
}
}
var person = new Person('Sunshine', , '女');
console.log(person.age); // undefined
console.log(person.name); // Sunshine
console.log(person.show()); // 18====女
注:this指向的都是共有的属性和方法,而直接通过var声明的则属于私有变量(即外部不可访问变量),然后通过一个共有的show方法将私有的age和sex输出。当然show方法也要通过this声明才可以哟,否则的话show方法也是不可访问的。
类和对象
1、类:一类具有相同特征(属性)和行为(方法)的集合。
比如,人类具有身高、体重等属性,吃饭、大笑等行为,所以,我们可以把人划分为一类。
2、对象:从类中,拿出具有确定属性值和方法的个体。
比如,张三-->属性:身高180体重180 方法:说话-->我叫张三,身高180
3、类和对象的关系:
①类是抽象的,对象是具体的(类是对象的抽象化,对象是类的具体化)
②类是一个抽象的概念,只能说类有属性和方法,但是不能给属性赋具体的。比如,人类有姓名,但是不能说人类的姓名叫什么。
对象是一个具体的个例,是将类中的属性进行具体赋值而来的个体。
比如,张三是一个人类的个体。可以说张三的姓名叫张三。也就是张三对人类的每一个属性进行了具体的赋值,那么张三就是由人类产生的一个对象。
4、使用类和对象的步骤:
1)创建一个类(构造函数):类名必须使用大驼峰法则。即每个单词首字母都要大写
function 类名(属性1){
this.属性1=属性1;
this.方法=function(){
//方法中要调用自身属性,必须使用this.属性
}
}
2)通过类实例化(new)出一个对象。
var obj=new 类名(属性1的具体值);
obj.属性; 调用属性
obj.方法; 调用方法
3)注意事项:
①通过类名,new出一个对象的过程,叫做"类的实例化"。
②类中的this,会在实例化的时候,指向新new出的对象。
所以,this.属性 this.方法实际上是将属性和方法绑定在即将new出的对象上面。
③在类中,要调用自身属性,必须使用this.属性名。如果直接使用变量名,则无法访问对应的属性。
function Person(name,age){
this.name=name;
this.age=age;
this.say=function(content){
//在类中,访问类自身的属性,必须使用this.属性调用。
alert("我叫"+this.name+",今年"+this.age+"岁,我说了一句话:"+content);
}
}
var zhangsan=new Person("姐姐",);
zhangsan.say("你好呀");
④类名必须使用大驼峰法则,注意与普通函数区分。
面向对象的两个重要属性
1)constructor:返回当前对象的构造函数。
2)instanceof:检测一个对象是不是一个类的实例;
>>>lisi instanceof Person //true √ lisi是通过Person类new出的
>>>lisi instanceof Object //true √ 所有对象都是Object的实例
>>>Person instanceof Object //true √ 函数本身也是对象
成员属性、静态属性和私有属性
1、在构造函数中,使用this.属性声明。或者在实例化出对象以后,使用"对象.属性"追加的,都属于"成员属性或成员方法"。也叫"实例属性或实例方法"。
成员属性/方法,是属于由类new出的对象的。
需要使用"对象名.属性名"调用。
【静态属性与静态方法】
2、通过“类名.属性名”、“类名.方法名”声明的属性和方法,称为静态属性、静态方法。也叫类属性和类方法。
类属性/类方法,是属于类的(属于构造函数的)
通过"类名.属性名"调用。
3、成员属性是属于实例化出的对象的,只能使用对象调用。
静态属性是属于构造函数的,只能使用类名调用。
[私有属性和私有方法]
4、在构造函数中,使用var声明的变量称为私有属性;
在构造函数中,使用function声明的函数,称为私有方法;
function Person(){
var num=;//私有属性
function func(){}//私有方法
}
私有属性和私有方法的作用域,只在构造函数内容有效。即只能在构造函数内部使用,在构造函数外部,无论使用对象名还是类名都无法调用。
JavaScript中的this指向详解
1、谁最终调用函数,this最终指向谁(记住!)
①this指向谁,不应考虑函数在哪声明,而应该考虑函数在哪调用!!!
②this指向的永远只可能是对象,而不可能是函数。
③this指向的对象,叫做函数的上下文context,也叫函数的调用者。
2、this指向的规律!!!(跟函数的调用方式息息相关,记住这点,相信你一定会分清this指向哒)
①通过函数名()调用的,this永远指向window
②通过对象.方法调用的,this指向这个对象。
③函数作为数组中的一个元素,用数组下标调用的,this指向这个数组
④函数作为window内置函数的回调函数使用,this指向window。 setInterval setTimeout 等。
⑤函数作为构造函数,使用new关键字调用,this指向新new出的对象。
var fullname = 'John Doe';
var obj = {
fullname: 'Colin Ihrig',
prop: {
fullname: 'Aurelio De Rosa',
getFullname: function () {
return this.fullname;
}
}
};console.log(obj.prop.getFullname()); //Aurelio De Rosa
// 函数的最终调用者 obj.prop var test = obj.prop.getFullname;
console.log(test()); //John Doe
// 函数的最终调用者 test() this-> windowobj.func = obj.prop.getFullname;
console.log(obj.func()); //Colin Ihrig
// 函数最终调用者是objvar arr = [obj.prop.getFullname, , ];
arr.fullname = "JiangHao"; //JiangHao
console.log(arr[]()); // 函数最终调用者数组
class 与构造函数的区别?
构造函数
function Circle (x, y, r, color) {
this.x = x
this.y = y
this.r = r
this.color = color
} Circle.prototype.render = function () {
ctx.beginPath()
ctx.arc(this.x, this.y, this.r, , Math.PI * , true)
ctx.fillStyle = this.color
ctx.fill()
} Circle.prototype.update = function () {
this.x +=
}
class
class Circle {
constructor (x, y, r, color) {
this.x = x
this.y = y
this.r = r
this.color = color
}
render () {
ctx.beginPath()
ctx.arc(this.x, this.y, this.r, , Math.PI * , true)
ctx.fillStyle = this.color
ctx.fill()
}
update () {
this.x +=
}
}






