2018-11-23 面向对象4 ES6

面向对象补充:

JavaScript 通过构造函数生成新对象,因此构造函数可以视为对象的模板。实例对象的属性和方法,可以定义在构造函数内部。
通过构造函数为实例对象定义属性,虽然很方便,但是有一个缺点。同一个构造函数的多个实例之间,无法共享属性,从而造成对系统资源的浪费。
JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。
JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。这个对象就是函数的原型。

  • eg:1继承
    效果如下:


    25.1继承.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
let p = new F('小明','很胖');
function F(name ,skill){
    this.name = name;
    this.skill = skill;
}
F.prototype.shou = 2;
F.prototype.showName = function(){
    //字符串模板  ''  ""  `${}`
    return `我的名字叫做:${this.name}`;
}
F.prototype.showSkill = function (){
    return `我的技能是:${this.skill}`;
}
console.log(p.showName());
console.log(p.showSkill());

function Stu(name,skill,use){
    F.apply(this,[name,skill]);
    this.use = use ;
}
console.log(Stu.prototype.constructor);
Stu.prototype = new F('','');
console.log(Stu.prototype.constructor);
Stu.prototype.constructor = Stu;
console.log(Stu.prototype.constructor);
let liming = new Stu('李明','包揽了整个高中英语','use  less');
console.log(liming.showName());
console.log(liming.showSkill());

</script>
</body>
</html>
原型链:

JavaScript 规定,所有对象都有自己的原型对象(prototype)。一方面,任何一个对象,都可以充当其他对象的原型;另一方面,由于原型对象也是对象,所以它也有自己的原型。因此,就会形成一个“原型链”(prototype chain):对象到原型,再到原型的原型……

如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了(多继承)

  • eg:2多继承
    效果如下:


    25.2多继承.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
function F(name,skill){
    this.name = name;
    this.skill = skill;
}

F.prototype.shou = 2;
F.prototype.showName = function(){
    //字符串模板''\""\`${}`
    return `我的名字叫做:${this.name}`;
}
F.prototype.showSkill = function(){
    return `我的技能是:${this.skill}`;
}
function M(sex){
    this.sex = sex;
}
M.prototype.showSex = function(){
    return `我的性别是:${this.sex}`;
}
function W(use){
    this.use = use;
}
W.prototype.showUse = function(){
    return`我的功能是:${this.use}`;
}
function Stu(name,skill,sex,use){
    F.apply(this,[name,skill]);
    M.call(this,sex);
    this.use = use;
}

Stu.prototype = Object.create(F.prototype);
Object.assign(Stu.prototype,M.prototype);
Object.assign(Stu.prototype,W.prototype);
Stu.prototype.constructor = Stu;
let z = new Stu('李华','高中英语','男','包揽了整个高中英语');
console.log(z.showName());
console.log(z.showSkill());
console.log(z.showSex());
console.log(z.showUse());
</script>
</body>
</html>
  • eg:3函数实现多继承
    效果如下:


    25.3函数实现多继承.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
function F(name,skill){
    this.name = name;
    this.skill= skill;
}
F.prototype.shou=2;
F.prototype.showName = function(){
    //字符串模板''\""\`${}`
    return `我的名字叫做:${this.name}`;
}
F.prototype.showSkill = function (){
    return `我的技能是:${this.skill}`;
}

function M(sex){
    this.sex = sex;
}
M.prototype.showSex = function(){
    return `我的性别是:${this.sex}`;
}

function Stu(name,skill,sex,use){
    this.use= use;
}
Stu.prototype.extends = function(obj,...man){
    obj.apply(this,[...man]);   //结构数组
    Object.assign(Stu.prototype,obj.prototype);
    Stu.prototype.constructor=Stu;
}

let z =new Stu('包揽了整个高中英语');
z.extends(F,'李明','高中英语');
z.extends(M,'男');

console.log(z.showName());
console.log(z.showSex());
console.log(z.showSkill());
</script>
</body>
</html>
  • eg:4.对象扩展
    效果如下:


    25.4扩展.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
    function f(...m){
        console.log([...m]);    //扩展运算符(...)
    }
    f(1,222,333);
    </script>
</body>
</html>

Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。

那么,Object.prototype对象有没有它的原型呢?回答是Object.prototype的原型是null。null没有任何属性和方法,也没有自己的原型。因此,原型链的尽头就是null。

  • eg:5单方面的继承
    效果如下:


    25.5单方面的继承.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        function F(){

        }
        F.prototype.h= function(){
            console.log('h');
        }
        F.prototype.m=function(){
            console.log('m');
        }

        function L(){

        }
        L.prototype.m =function(){
            F.prototype.m.call(this);
        }

        let l = new L();
        l.m();
    </script>
</body>
</html>

constructor:
prototype对象有一个constructor属性,默认指向prototype对象所在的构造函数。

ES6

1、ES6面向对象:

class ----- 构造函数
对象 ----- 实例对象

  • eg:6ES6对象简写
    效果如下:


    25.6ES6对象简写.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
    let name = '小明';
    let skill = '高中英语';
    let s = Symbol('s');    //对一无二的值
    let ss = Symbol('ss');
    console.log(s);
    console.log(ss);
    const obj ={
        name,
        skill,
        say(){
            console.log('say');
        },
        [s]:s,
    };

    console.log(obj.name)
    obj.say();
    console.log(obj[s])
    </script>
</body>
</html>
  • eg:7面向对象
    效果如下:


    25.7ES6面向对象.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        const a = Symbol(); //常量
        class Person{
            constructor(name,skill){    //构造函数,new的时候自动的调用的,用于初始化的。自动传递参数
                this.name = name;
                this.skill=skill;
            }   //在此处有constructor所以不能有逗号
            showName(){
                console.log(`我的名字:${this.name}`);
            }
            showSkill(){
                console.log(`我的技能:就是${this.skill}`);
            }
            [a](){
                console.log(`我是Symbol数据类型的函数名`);
            }
        }
        console.log(typeof Person);
        let p1 =new Person('李明','高中英语');
        p1.showName();
        p1.showSkill();
        p1[a]();
    </script>
</body>
</html>
  • ES5面向对象是模拟面向对象。
    实例:
    人类 张三
    动物类 熊猫
    鸟类 黄鹂
    植物类 仙人球
    哺乳动物 人

(1)、constructor: 类的构造函数,类在实例化的时候自动调用。参数自动传递。
(2)、class 的属性名可以是变量,但是这个变量需要使用[]包装起来,表示变量的解析。
class的内在本质还是一个function。

  • eg:9class结构
    效果如下:


    25.9class结构.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        class P{
            constructor(name){
            this.name=name;
            }
            say(){
                console.log(this)
                console.log(this.name);
            };
        }
        let p1 =new P('李明');
        p1.say();

        let {say}=p1;

        say.bind(p1);
    </script>
</body>
</html>

对于ES5的构造函数来说,本质上定义的是一个函数,函数和变量一样,具有提升的特性,所以可以在构造函数的申明之前进行实例化。 class没有提升,所以在创建类对象的时候一定要保证类是先加载的。

  • eg:8class没有提升
    效果如下:


    25.8class没有提升.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
    let pp= new P();
    class P{
        constructor(){//constructor构造函数是class必须的,即使没有声明 ,那么class也会自动的添加一个空的constrcutor函数。
        }
    }
    </script>
</body>
</html>
2、setter与getter:

封装class内部成员属性的作用。
语法。
自动能调用。
(1)、set 语法定义的函数,外部在调用函数名为属性的属性设置值的时候调用。
(2)、get 语法定义的函数。外部在获取这个函数名为属性的属性的时候调用。

  • eg:10get 与 set
    效果如下:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
        class P{

        }
        const Person = class{
            constructor(name){
                this.name= name;
            }
            /*
            set age(value){
                设置这个值的时候会自动调用console.log('这里调用参数的设置');
                let c = value ;
                console.log(c);

            } */
            get age(){
                console.log('这里调用了参数的获取')
                return 111111111;
            }
        }

        let p1 =new Person('李明');
        console.log(p1.name)
        p1.name = '高中英语';       //公共属性

        console.log(p1.age)
        p1.age =22222222222222222;
        console.log(p1.age)
    </script>
</body>
</html>

有的时候我们需要不创建你对象,直接使用类去执行某些事情,这个时候就可以设计静态方法。
(3)、static 静态的。不需要实例化对象去调用的方法。
静态方法里面的this指类本身。而不是对象。
静态方法直接使用类名调用,不能使用对象调用。
静态的类: Math
实例:
var proxy = new Proxy(target, handler);
target : 要进行代理的对象。
handler:代理的规则。
代理:帮助做一些事情。

  • eg:11 static
    效果如下:


    25.11static.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
class P {
    constructor(){}
    say(){
        console.log(this);  //实例对象
        console.log('1111111111111');
    }
    static ss(){
        console.log(this);  //class
        console.log('2222222222222222222');
    }
}
let p = new P();
p.say();

P.ss();
</script>
</body>
</html>

(4)extends继承

  • eg:12extends
    效果如下:


    25.12extends.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
    <script>
    class F{
        constructer(name){
            this.name = name;
        }
        say(){
            console.log(this.name);
        }
        static s(){
            console.log('ssssssssssssssssssss');
        }
    }
    class W extends F{
        constructor(name,age,skill){
            //如果没有设置constructor,那么这个构造函数就是继承自父类。
            //但是一旦自己设置了constructor函数,规定在内部必须调用父亲的构造函数
            super(name);    //表示调用父类的构造函数

            this.age = age ;
            this.skill = skill;
            this.name = name;
        }
        eat(){
            console.log('eat');
        }
        say(){      //重写 overriding
            super.say();    //super表示父级
            console.log('33333333333333');
        }
    }

    let t = new W('lalalalalalala');
    t.say();
    t.eat();

    W.s();      //继承静态的方法
    </script>
</body>
</html>

(5)、proxy
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。Proxy 这个词的原意是代理,用在这里表示由它来“代理”某些操作,可以译为“代理器”。

  • eg:13proxy
    效果如下:


    25.13proxy.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
const obj = {//const
    a:12,
    b:'abc',
    c:1111111,
    d:'liming'
};
const c = new Proxy(obj,{
    get: function(a,b,c){
        //console.log(a);//第一个参数是代理对象
        //console.log(b);  //代理的属性
        //console.log(typeof  a[b])
        //console.log(a[b].prototype)

        if(typeof a[b] =='number'){
            return a[b];
        }
        return 2;
    }
});

console.log(c.d);
</script>
</body>
</html>

(6)、reflect
*Reflect*对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。*Reflect*对象的设计目的有这样几个。
Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在ObjectReflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。

效果如下:


25.reflect.jpg
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Document</title>
</head>
<body>
<script>
const obj = {
    a:122222,
    b:'liming'
};

let c = new Proxy (obj,{
    set:function(target,name,value,receiver){
        var success = Reflect.set(target,name,2,receiver);
        console.log(success);
        if(success){

        }
        return success;
    }
});
c.a = 1111111;
console.log(c.a);
</script>
</body>
</html>
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,997评论 6 502
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,603评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,359评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,309评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,346评论 6 390
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,258评论 1 300
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,122评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,970评论 0 275
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,403评论 1 313
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,596评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,769评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,464评论 5 344
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,075评论 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,705评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,848评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,831评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,678评论 2 354