面向对象JS ES5/ES6 类的书写 继承的实现 new关键字执行 this指向 原型链

一 、什么是面向对象?

  面向对象(Object Oriented),简写OO,是一种软件开发方法。

  面向对象是一种对现实世界理解和抽象的方法,是计算机编程技术发展到一定阶段后的产物。

  面向对象的概念和应用已超越了程序设计和软件开发,扩展到如数据库系统、交互式界面、应用结构、应用平台、分布式系统、网络管理结构、CAD技术、人工智能等领域。

  面向对象是相对于面向过程来讲的,面向对象方法,把相关的数据和方法组织为一个整体来看待,从更高的层次来进行系统建模,更贴近事物的自然运行模式。

编程范式

  一般可以分为两种:

    声明式,告诉计算机应该做什么,但不指定具体要怎么做。如:html,css等

    命令式,关注计算机执行的步骤,即一步一步告诉计算机先做什么再做什么。如:js,c++,java,c#,python等

  其中命令式编程又可以为两类

    面向过程:

    将我们要解决问题所需要的步骤分析出来,然后用函数把这些步骤一步一步实现(有序步骤),关注细节。

    面向对象:

    将问题中的对象抽象出来,既把构成问题的事物分解成各个对象,而解决问题的不是一个个过程化的步骤,

    而是利用对象描述、处理“问题”的行为集合(离不开面向过程)。

二、面向对象的基本概念

1、对象

  对象的含义是指具体的某一个事物,即在现实生活中能够看得见摸得着的事物,有句话叫做:万物皆对象。

  对象是类的具体实例,对象的抽象是类。

2、类

  类是具有相同特性(数据元素)和行为(功能)的对象的抽象,代表一类事物的抽象描述。

  在代码中:类好比是一个模板,可以批量生产。

  类是对象的抽象,类的具体化就是对象。

  类的实现

  原本JS不支持面向对象(oo),所以在ES5用函数模拟出类,在ES6时加入语法糖,书写起来更加清晰、更像面向对象编程的语法。

  类的本质是函数:构造函数+全局公共区域 prototype。

ES5

//混合模式:构造函数模式+原型模式
function Person(name, age) {//构造函数模式
    this.name = name;  /*属性*/
    this.age = age;
    this.study = function () {
        console.log(this.name + ‘在运动‘);
    }
}

//原型模式 prototype,原型链上面的属性会被实例对象共享
Person.prototype.sex = "男";//共有的属性
Person.prototype.exercise = function () {//共有的函数
    console.log(this.name + ‘在锻炼‘);
}

//类的静态属性和方法不会被实例对象共享
Person.num = 11234;//定义静态属性
Person.printNum = function () {//定义静态方法
    console.log(this.num);
}//注:函数也是一个对象,所谓的静态属性方法,本质就是给名为Person的对象添加了属性和方法

var stu = new Person(‘张三‘, 20);
console.log(stu);//Person { name: ‘张三‘, age: 20, study: [Function] }
console.log(stu.sex);//男
stu.study();//调用自带方法 => 张三在运动
stu.exercise(); //调用原型方法 => 张三在锻炼

console.log(Person.num);//11234    静态属性和方法 通过 类名.方法(属性名) 调用或访问
console.log(stu.num);//undefined    实例对象不能使用
Person.printNum();//11234
stu.printNum();//报错 stu.printNum is not a function

ES6

class Person {
    constructor(name, age) {//构造函数
        this.name = name;  /*属性*/
        this.age = age;
        this.sex = "男";
        this.study = function () {
            console.log(this.name + ‘在运动‘);
        }
    }

    static num = 11234;//定义静态属性 
    static printNum() {//定义静态方法
        console.log(this.num);
    }
    exercise() {//共有的函数
        console.log(this.name + ‘在锻炼‘);
    }
}
var stu = new Person(‘张三‘, 20);
console.log(stu);//Person { name: ‘张三‘, age: 20, sex: ‘男‘, study: [Function] }
console.log(stu.sex);//男
stu.study();//张三在运动
stu.exercise(); //张三在锻炼

console.log(Person.num);//11234
console.log(stu.num);//undefined
Person.printNum();//11234
stu.printNum();//报错 stu.printNum is not a function

注:两种方式都能成功的声明一个Person类,现在一般就用ES6方式,但是其实内部是用ES5的方式运行的,ES6方式相当于一个语法糖。

  关于new

    每次使用new关键字会执行的步骤:

      1、创建一个空的新对象,作为将要返回的对象实例
          var obj = {};
      2、将该对象的__proto__(隐式原型)指向创建该对象的类的原型对象
          //假设类叫做 A
          obj.__proto__ = A.prototype;
      3、将构造函数环境中的this,指向该对象
          相当于:this = obj;//意识到位,代码这样写是错误的
      4、执行构造函数中的代码,并返回刚刚创建的新对象

注:class 定义的类,必须使用new关键字调用,不然会报错,

  new关键字总是返回一个对象,如果new 普通函数,会返回一个空对象。

  关于构造函数constructor

    
  constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。

  在类中必须存在构造函数,可以不书写,会默认补一个空构造constructor{}

  返回值
    构造函数也有返回值,默认返回实例对象(即this),可以更改,若改为基本数据类型的返回值,则不影响函数。
    若改为复杂数据类型的返回值,则会直接将该返回值直接返回,会导致返回值不再是原来类的实例对象,

三、面向对象三大特征

1、封装

  隐藏内部细节,不暴露在外面;做到信息的隐藏,不关心具体怎样实现的,只需要知道能达到效果就行了。

  具体表现形式:
      函数    是对于算法的封装
      类    是对于属性和方法的封装

2、继承

  子类继承父类的所有属性和方法,并且扩展自己的属性和行为。

  类与类之间的关系:is a(是一个)  例如:学生——>人类

  实现

 

function Student(){
    Person.call(this);    //对象冒充实现继承 对象冒充可以继承构造函数里面的属性和方法   但是没法继承原型链上面的属性和方法
}
//原型链实现继承  原型链实现继承:可以继承构造函数里面的属性和方法 也可以继承原型链上面的属性和方法
Student.prototype = Object.assigin(Person.prototype);   //与拷贝类似,但不同
//Student.prototype=new Person();   //这种方法功能是能实现,但是太矬了
// Student.prototype = Object.create(Person.prototype); //没有将create的储存起来,只是利用原型链找到有属性的父类

改变this指向的三个函数实例方法

var name = 99;
function foo(a, b) {
    console.log(this.name, a, b);//this本来指向全局的 name=99
}
let zs = {
    name: "zs"
}
let ls = {
    name: "ls"
}
//call方法,可以指定函数内部this的指向(即函数执行时所在的作用域),然后在所指定的作用域中,调用该函数第一个参数(对象)为指向。
foo.call(ls, 1, 2);//ls 1 2
//apply方法的作用与call方法类似,也是改变this指向,然后再调用该函数。唯一的区别就是,它接收一个数组作为函数执行时的参数
foo.apply(zs, [2, 3]);//zs 2 3
//bind方法用于将函数体内的this绑定到某个对象,然后返回一个新函数。这个要主动调用
let bar = foo.bind(zs);
bar(3,4);//zs 3 4

  ES6

// 图形祖宗
        class Graph {
            constructor(color, top, left) {
                this.color = color;
                this.top = top;
                this.left = left;
                this.node = null;
            }
            creatNode() { }
            addNode() {
                document.body.appendChild(this.node);
            }
        }
// 矩形
        class Rectangle extends Graph {
            constructor(color, top, left, lengthX, lengthY) {
                super(color, top, left);
                this.lengthX = lengthX;
                this.lengthY = lengthY;
            }
            creatNode() {
                this.node = document.createElement(`div`);
                this.node.style.position = "absolute";
                this.node.style.background = this.color;
                this.node.style.top = this.top + "px";
                this.node.style.left = this.left + "px";
                this.node.style.width = this.lengthX + "px";
                this.node.style.height = this.lengthY + "px";
            }
        }

  extends 扩展  从子类,扩展到父类  即继承父类

  super 超类  继承父类  用于调用父亲的构造,必须与extends关键字一起使用,且只能在构造函数中所有的this之前书写

3、多态

方法(行为)  相同的行为不同的实现  传的参数不一样,决定了实现方法不一样

代码中的多态:  
    重载  参数的不同,实现不同  js自带,因为js没有严格的指定参数的个数类型

    重写  父亲的行为,儿子重写一个覆盖了

四、this和原型对象

this指向问题

1、箭头函数中,没有自己的this,它借用声明箭头函数处(环境中的)的this(就固定这个值)

2、谁调用,指向谁

3、事件监听函数中,this指向,绑定监听函数的那一个元素节点(谁绑,指向谁)

4、当一个函数没有被其他对象调用时,(普通调用),this指向全局对象(严格模式下面是undefined)

5、在执行构造函数时(new),this指向新创建的对象

原型对象

规则:

所有function创建的对象,都叫做函数对象(函数)

所有函数对象上都有一个原型对象,prototype

所有对象上都有一个隐式原型对象,__proto__,指向创建该对象的构造函数的原型对象

所有原型对象上都有一个constructor对象,指向该原型对象所在的构造函数本身

或者这样说:

对象可以分为函数对象(所有直接通过function创建的对象)和一般对象(其他对象),所有的对象在创建时,都会创建一个对应的原型对象

函数对象的原型对象为:函数.prototype,函数.prototype上都有一个constructor对象,指向该原型对象所在的构造函数本身

一般对象的原型对象被称为隐式(和函数对象的原型对象相区分)原型对象: 对象.__proto__,指向创建该对象的构造函数的原型对象

原型链:

一个对象通过自身的__proto__,一直向上链接,直到null,所构成的的链条,就是原型链

原型链作用:用来找属性

当一个对象在访问自身某个属性时,会先在自己身上找,没有找到就通过原型链(__proto__),层层向上找,直到找完为止

若找完整个原型链都没有找到,那么该属性的值就是,undefind。

原文地址:https://www.cnblogs.com/jiayouba/p/12004285.html

时间: 2024-07-30 18:50:45

面向对象JS ES5/ES6 类的书写 继承的实现 new关键字执行 this指向 原型链的相关文章

js继承之二(组合模式=借用构造函数+原型链方式)

借用构造函数模式:不能继承原型上的属性,可以避免引用类型修改问题 原型链:能够继承原型上的属性,会发生引用类型修改 so:敲黑板! function CarModel(c){ this.color=c||"白色"; this.arr=[1,2,3]; this.getColor=function(){ console.log('我的颜色是'+this.color); } } CarModel.prototype.test="lla"; function Car(br

Atitit js es5 es6新特性 attilax总结

1.1. JavaScript发展时间轴:1 1.2. 以下是ES6排名前十的最佳特性列表(排名不分先后):1 1.3. Es6 支持情况 基本chrome ff 360se8全面支持了2 2. ECMAScript 2015(ES6)的十大特征 – WEB前端开发 - 专注前端开发,关注用户体验.html2 1.1. JavaScript发展时间轴: 1.1995:JavaScript诞生,它的初始名叫LiveScript. 2.1997:ECMAScript标准确立. 3.1999:ES3出

java中面向对象的三大特性:封装、继承、多态和关键字instanceof

1.封装: 使用private关键字,使得外界不能够直接访问类的属性: 提供setter和getter方法进行设置和获取: 好处:提升程序的安全性,让外界不能够直接进行访问:还可以对设置的属性进行输入限制: public class anli1 {private String name;private String sex;public String getName() { return name;}public void setName(String name) { this.name = n

es5继承和es6类和继承

es6新增关键字class,代表类,其实相当于代替了es5的构造函数 通过构造函数可以创建一个对象实例,那么通过class也可以创建一个对象实列 /* es5 创建一个person 构造函数 */ function person (name,age) { this.name = name this.age = age } /* 定义原型链上的方法sayholle */ /* 为什么要将方法定义在原型上,定义在原型上的方法,所有的实例对象都共享 不会出现没实列一个对象都重新创建一个这个方法 */

JavaScript ES5类 原型 原型链 组合、原型、寄生式继承

ES5类 原型  原型链 继承 JavaScript中,原型是相对于构造函数(类)的叫法(或者说概念),原型链是相对于构造函数(类)的实例对象的叫法. 对于JavaScript对象,如果在对象自身上找不到该属性,那么就会向上沿着原型链继续查找该属性 创建一个ES5类 在ES5中,类是由函数名首字母大写的函数,通过关键字new创建的. 类的构造函数就是函数自身 一般情况下,ES5类的原型对象prototype是自身构造函数,该类的实例化对象的原型链对象__proto__也是该构造函数,这二者指向同

JS面向对象之继承——原型链

原型对象 每个javascript对象都有一个原型对象,这个对象在不同的解释器下的实现不同.比如在firefox下,每个对象都有一个隐藏的__proto__属性,这个属性就是“原型对象”的引用. 原型链 由于原型对象本身也是对象,根据上边的定义,它也有自己的原型,而它自己的原型对象又可以有自己的原型,这样就组成了一条链,这个就是原型链,JavaScritp引擎在访问对象的属性时,如果在对象本身中没有找到,则会去原型链中查找,如果找到,直接返回值,如果整个链都遍历且没有找到属性,则返回undefi

js继承之原型链继承

面向对象编程都会涉及到继承这个概念,JS中实现继承的方式主要是通过原型链的方法. 一.构造函数.原型与实例之间的关系 每创建一个函数,该函数就会自动带有一个 prototype 属性.该属性是个指针,指向了一个对象,我们称之为 原型对象.什么是指针?指针就好比学生的学号,原型对象则是那个学生.我们通过学号找到唯一的那个学生.假设突然,指针设置 null, 学号重置空了,不要慌,对象还存在,学生也没消失.只是不好找了. 原型对象上默认有一个属性 constructor,该属性也是一个指针,指向其相

js 原型链和继承(转)

在理解继承之前,需要知道 js 的三个东西: 什么是 JS 原型链 this 的值到底是什么 JS 的 new 到底是干什么的 1. 什么是 JS 原型链? 我们知道 JS 有对象,比如 var obj = { name: "obj" }; 我们通过控制台把 obj 打印出来: 我们会发现 obj 已经有几个属性(方法)了.那么问题来了:valueOf / toString / constructor 是怎么来?我们并没有给 obj.valueOf 赋值呀. 上面这个图有点难懂,我手画

ES5的类

1.最简单的类 function Person(){ this.name='张三'; this.age=20; } var p=new Person(); alert(p.name); 2.构造函数和原型链里面增加方法 function Person(){ this.name='张三';/*属性*/ this.age=20; this.run=function(){ alert(this.name+'在运动'); } } //原型链上面的属性会被多个实例共享 构造函数不会 Person.prot