zoukankan      html  css  js  c++  java
  • 对象与原型对象下篇



    迷途 2019/7/23 星期二 19:18:47

    迷途 2019/07/23 19:18:47
    如何対this的指向迸行修改。
    13-8-1 this指向的几神情况
    this指向当前対象
    遠个我們在学羽JS基拙的対象章や肘已経接触辻了,如果是在対象里面使用this ,一般来垪,美鍵字this是指它所在的対象。this 可以用在方法内,荻取対対象属性的訪向。示例如下:

    let person = {
    name : 'xiejie',age : 18,
    intro : function(){
    console. log(this);
    // { name; xiejie', age: 18, intro: [Function: intro] }
    console.log(My name is ${this. name},I'm ${this.age} years old' );1/ My name is xiejie,I'm 18 years old

    }
    }
    person. intro();

    再来看一个用枸造函数中this的指向,其突也是一-祥的指向当前対象,示例如下: 
    激活Windq



    迷途 2019/7/23 星期二 19:18:57

    迷途 2019/07/23 19:18:56

    代表着将A应用到B里面,但是作用域还是保留B的作用域。这就是JS里面经典的方法借用。我们来看一个具体的示例,如下:

          Let One = function(){

          this.name = "one";

          this. showName = function(){

          console. Log(this . name);}

    }  8lettwo={

          name : "two"};

          Let one = new 0ne() ;

          one. showName.call(two);://two

          /将one的showName万法应用到two.上面

          // two原本没有showName方法,我one借用后有了该方法

    接下来我们再来看一个经典的例子,为数组求最值

          Let arr = [3,15,8,1,2,17,11];

          Let max = Math. max. apply(this,arr);

    console. log(max);//17  激活Wi

          转到设置”这里我们借用了Math对象的max方法,将其应用到全局对象上面。注意这里的this是指向的全局



    迷途 2019/7/23 星期二 19:19:06

    迷途 2019/07/23 19:19:06
    可以看到,这里Student确实已经就继承到了Person,成功的访问到了name和age属性。但是,使用对象冒充来实现继承也有一个缺陷, 那就是无法继承到原型对象上面的属性,证明如下:

    Let Person = function ( name,age){
    this . name = name;this.age = age;

    }
    Person. prototype.test = function(){
    console. log("this is a test");

    }
    Let Student = function name, age, gender , score){
    this, temp = Person;// 将Pe rson构造函数作为Student的一个属性
    this. temp (name, age) ;//给Person构造函数里面的this. name以及this. age赋值delete this. temp;//this. temp已经无用,将其删除this, gender = gender;this.score = score;

    }
    Let xiejie = new Student("谢杰", 18,"男”,100);console. Log(xiejie. name);//谢杰console. log(xiejie.age);//18
    console. log(xiejie. gender);//男console. log(xiejie. score);//100
    xiejie. test();//TypeError: xiejie.test is not a function

    激活Win转到设置”以



    19:19:16
    迷途 2019/7/23 星期二 19:19:16

    class Person[

    constructor(name,age)
    this.name = name ;this.age = age;

    sayName()[
    console.log(' my name is $(this . name)' );

    2
    class Student extends Person[

    constructor(name , age , gender , score)i
    ѕuреr (nаmе, аgе);//ѕuреrftа іѢЅ#854ФЕthis.gender = gender;this.score = score;

    lR
    learn()f
    console.log("IV 'm learning");

    1
    let xiejie = new Student("xiejie" ,18,"male",100);console. log(xiejie. name);//xiejieconsole. log(xieiie.aqe);1118 I




    迷途 2019/7/23 星期二 19:19:26

    迷途 2019/07/23 19:19:26
    普通函数中this的指向
    还有一种情况,是this指向全局对象。当this是在全局中使用,或者是在函数中,但是该函数不作为对象的方法,只是作为普通函数被调用时,指向的就是全局对象(node里面是global对象,浏览器环境里面是window对象)。示例如下:

    Let test = function(){  N
    console. log(this);//globaL对象//在node里面,全局对象就是global对象
    //如果是在浏览器里面,那么全局对象代表window对象

    }
    test(); //普通函数调用, this 将会指向全局对象

    以普通函数的方式调用的时候,无论嵌套多少层函数,this 都是指向全局对象
    Let test = function(){
    Let test2 = function(){
    Let test3 = function(){
    console. log(this);//globaL对象

    激活Win活到设置”心

    1



    迷途 2019/7/23 星期二 19:19:36

    迷途 2019/07/23 19:19:35

          继承最大的好处,就在于代码复用。例如有两个类,这两个类的属性和方法基本相同,那么我们就可以考虑给这两个类写一个父类

          继承的缺点

          首先如果继承设计得非常复杂,那么整个程序的设计也会变得庞大和臃肿。甚至经常会出现"大猩猩与香蕉"的问题。"大猩猩与香蕉"这个名字来自于Erlang编程语言的创始人Joe Armstrong的文章:你想要一个香蕉,但是得到的是拿着香蕉和整个丛林的大猩猩。

          还有一一个问题就是,如果是像C+ +那样的多继承语言,那么还可能会遇到菱形继承的问题。这里我们首先来看一下什么叫做多继承。既然有多继承,自然就有单继承。单继承:所谓单继承,就是指只有一-个父类多继承:所谓多继承,就是指有多个父类

          菱形继承问题:首先需要说明,菱形继承问题只会在多继承里面才会出现。例如: A和B都继承Base类,假设Base类里面有一一个成员方法,那么A和B里面都会有这个成员方法,这个时候A和B两个类又都对这个成员方法进行了修改。接下来让一个C来同时继承A和B,那么这个时候就会产生一个问题,对于同名的方法,究竟使用哪-个,这就是所谓的菱形继承问题。这个是属于设计上的问题。

          不过,JavaScript是- -门单继承的语言,所以一定程度上避免了菱形继承的问题。



    迷途 2019/7/23 星期二 19:19:46

    迷途 2019/07/23 19:19:46
    现在书写JavaScript继承,基本上不会再使用对象冒充了,但是上面之所以要介绍对象冒充这种继承方式,是为了顺带引出JS中-个非常有特色的方法借用模式。这在JS中是相当灵活的一-种模式,不需要继承,就可以从父类或者原型上面借用相应的属性和方法。这里,我们先来介绍两个方法,分别是call()和apply()方法,cal和apply方 法都能继承另外-个对象的方法和属

    性,具体的语法如下:
    Funct ion. apply(obj, args )方法能接收两个参数obj:这个对象将代替Funct ion类里this对象
    args:这个是数组,它将作为参数传给Funct ion(args . >arguments)

    call:和apply的意思-样,只不过是参数列表不一样。
    Function. call(obj, [param1(, param2[, ...[, paramN]1])obj:这个对象将代替Function类里this对象params:这个是一个参数列表

    这两个方法除了参数的形式外基本上是相同的。call() 方法后面接收的是参数列表,而apply()方法后面则是接收的是一个数组。简单概括起来,可以写作如下的形式:

    激活Wi



    迷途 2019/7/23 星期二 19:19:54


          接下来我们再来看一个经典的例子,为数组求最值

          Let arr = [3,15,8,1,2,17,11];

          let max = Math. max. apply(this,arr);console. log(max);//17

          这里我们借用了Math对象的max方法,将其应用到全局对象上面。注意这里的this是指向的全局对象,然后将数组作为apply的第二个参数传入进去。  ξ



    迷途 2019/7/23 星期二 19:20:03

    迷途 2019/07/23 19:20:03
    接下来我们再来看一个例子,如下:
    var name = "PHP";Letobj={
    name : "JavaScript"

    }
    let show = function(){
    console. Log("Hello," + this, name); 

    }
    obj.fn = show;// 将showl)方法赋值给obj对象的fn属性obj. fn();//Hello, JavaScript
    show();//Hello, undefined如果是浏览器环境如是Hello, PHP

    这里我们将show()方法赋值给obj对象的fn属性,所以在执行obj. fn()时是以对象的形式来调用的,this 将会指向obj对象。而后面的show()方法则是单纯的以普通函数的形式来进行调用的。所以this指向全局对象。

    激活Winc



    迷途 2019/7/23 星期二 19:20:11

    REAEi -#ôtÆ, ïẞüXT#ÆẞX, $ẞF:
    let Test = (name,age) => [
    this. name = name;this.age = age;

    );
    let. test = new Test("xiejie",18);
    1/TypeError: Test is not a constructor




    迷途 2019/7/23 星期二 19:20:34

    接下来我们将i()函数修改为箭头函数
    var name = "JavaScript";letobj={
    name : "PHP",
    test : function(){ 上
    Leti=()=>{
    console. log(this. name);
    //由于i为一个箭头函数,所以this是指向外层的//所以this . name将会打印出PHP

    }i();

    }
    }
    obj. test();//PHP




    迷途 2019/7/23 星期二 19:20:45

    可以看到,普通函数作为对象的一个方法被调用时,this 的指向是指向的这个对象,上 面的例子中就是指向的obj这个对象,this.x 的值为10。当然这是我们最早在JS基础部分的对象一章就已经介绍过的内容。

    接下来我们来看一下箭头函数以对象的方式被调用的时候的this指向,如下:
    Letobj={
    X:10,
    test : ()=>{
    console. log(this);// {

    console. log(this.x);// undefined
    }
    }
    obj. test();/(
    // undefined

    7



    迷途 2019/7/23 星期二 19:20:53

    避免引起问题的另一种方 式使用extends子类化-一个已经创建好了的类,从而创建自己的类。例如,我们可以像下面一样,通过继承内置的Number类来创建自己的Number类

    cLass myNum extends Number{
    const ructor(...args){
    super(...args);

    }
    isEven(){
    return this%2 ===。

    }
    }
    Let i = new myNum(42);
    //无论是新类添加的方法还是Number类里面的方法都可以使用console. log(i. isEven())://true
    console. log(i. toFixed(2));//42.00

    激活Windd站到”设置”以测




    迷途 2019/7/23 星期二 19:21:10

    迷途 2019/07/23 19:21:09
    Let mixin = function(target,...objects){
    //首先遍历要混入的对象用object 来进行接收每一个要混 人的对象for(const object of objects){
    //要混入的必须是对象所以先进行一个类 型的判断if(typeof object === 'object'){
    //取出混入对象的每. .个属性
    for(const key of 0bject. keys(object)){
    //如果属性所对应的值为对象继续递归调用mixinif(typeof object[key] === 'object'){
    target[key] = Array. isArray(object[key]) ? [] ; {};mixin(target [key] , object [key]);}else{
    //否则就直接混入到目标对象里面
    0bject. assign(target , object);

    }
    }
    }
    }
    return target;



    19:21:21
    迷途 2019/7/23 星期二 19:21:21

    迷途 2019/07/23 19:21:20

    this指向郷定事件的元素

    美于遠一-狆this的指向,我們在学刃事件章や吋也接触辻了。如果是DOM元素郷定事件,那幺事件処理函数里面的this指向郷定了事件的元素。込个地方一定要注意它和target的区別,target 是指向触友事件的元素。示例如下:

          <body>

          <ul id="color-list">

          <li>red</li>

          <li>yellow</li><li>blue</li><li>green</li><li>black</li><li>white</li></ul>

          <script>

          1/ this是郷定事件的元素

          1/ target是触友事件的元素和srcElememnt等价

          let colorList = document. getElementById("color-list");colorList . addEventL istener("click", function (event) {

          console. log('this:', this);

          console. log('target:', event. target);

          console. log('srcElement:', event.srcElement);

          })  激活Windd</script>  転刳“優置”以測</ body>



    迷途 2019/7/23 星期二 19:21:30

    迷途 2019/07/23 19:21:30

          箭头函数的this指向

          当我们的this是以函数的形式调用时,this 指向的是全局对象。不过对于箭头函数来讲,却比较特殊。箭头函数的this指向与其他函数不一样,它的this指向始终是指向的外层作用域。

          我们先来看一个普通函数作为对象的-一个方法被调用时,this 的指向,如下:

          LetpbjF{

          x: 10,

          test : function(){ L

          console. log(this);//指向obj对象console. log(this.x);//10}}

          obj. test();

          / { x: 10,test: [Function: test] }// 10

          可以看到,普通函数作为对象的一个方法被调用时,this 的指向是指向的这个对象,上 面的例

          子中就是指向的obj这个对象,this.x 的值为10。当然这是我们最早在JS基础部分的对象元章Nin就已经介绍过的内容。  转到”设置”以



    迷途 2019/7/23 星期二 19:21:41

    迷途 2019/07/23 19:21:40
    13-8-2改变this的指向
    在前面的小节中,我们已经总结出了在JavaScript中关于this 指向的几种情况。但是,这个this的指向,我们是可以进行修改的。接下来我们就来看一看几种修改this指向的方法。

    使用call或者apply来修改this指向
    前面我们有介绍过JS中的方法借用模式,使用call()或者apply()可以借用其他对象的方法而不用通过继承。实际上,call() 和apply()也算是间接修改了this的指向。示例如下: ;

    let Test = function(){
    this.name = "JavaScript";this,say = function(){
    console. log(这是${this.name} );

    }
    Let test = new Test();
    test. say();//这是JavaScriptLet a = {name :“PHP"};test. say.call(a);//这是PHP

    激活Win转到设置”心




    迷途 2019/7/23 星期二 19:21:50

    迷途 2019/07/23 19:21:49
    要避免只是浅复制,我们可以自己创建一个mixin()函数,该函数会对一个对象的所有属性进行深度的复制,书写如下:

    Let mixin = function(target,...objects){
    //首先遍历要混入的对象用object来进行接收每一 个 要混入的对象for(const object of objects){
    /要混入的必须是对象所以先进行一个 类型的判断if(typeof object === 'object'){
    //取出混入对象的每一个属性
    for(const key of 0bject. keys(object)){
    //如果属性所对应的值为对象继续递归调用mixinif(typeof object[key] === 'object'){
    target[key] = Array. isArray(object[key]) ? [] : {};mixin(target [key] , object [key]);}else{
    //否则就直接混入到目标对象里面
    0bject. assign(target , object);

    }
    }
    }
    }
    }
    return target;

    激活Win有了该函数以后,我们就可以使用该函数来进行对象的混入,还是演示上面的那个例子:临到设置公




    迷途 2019/7/23 星期二 19:21:58


    有了该函数以后,我们就可以使用该函数来进行对象的混入,还是演示,上面的那个例子:

          Let司={};Letb = {

          test : [1,2,3]

          mixin(a,b);

          console. log(a.test);//[ 1,2, 3 ]b. test. push(4);

          console. log(a. test);//I I, 2, 3 ]console. log(b.test);//l 1, 2, 3, 4」

    可以看到,这一次我们再次修改b对象的test属性值,为数组推入一个元素时,没有影响到a对象的test属性值了。说明我们这一次是进行了深度的复制。



    迷途 2019/7/23 星期二 19:22:07

    迷途 2019/07/23 19:22:06
    这里我们借用了test对象的say()方法,本来对于test对象的say()方法来讲,this是 指向test对象的,但是现在a对象借用了say()方法以后,this是指向a对象的,所以打印出了"这是PHP"

    通过bind(方法来强行绑定this指向
    第二种方式是可以通过bind()方法来强行绑定this的指向。bind() 方法的语法如下:fun. bind(thisArgl, arg1l, arg2[, ...111)参数:

    ●thisArg 当绑定函数被调用时,该参数会作为原函数运行时的this指向。
    ●arg1, arg2, .... 当绑定函数被调用时,这些参数将置于实参之前传递给被绑定的方法。

    我们来看一个具体的示例,如下:



    迷途 2019/7/23 星期二 19:22:17

    迷途 2019/07/23 19:22:17
    由于只是浅复制,所以当我们改变b对象的test属性,往数组里面添加一个元素时,a对象的test属性也会发生相应的变化。

    要避免只是浅复制,我们可以自己创建一个mixin()函数,该函数会对一个对象的所有属性进行深度的复制,书写如下:

    Let mixin = function(target,.. objects){
    1/首先遍历要混入的对象用objeft 来进行接收每一个要混 人的对象for(const object of objects){
    //要混入的必须是对象所以先进行一个 类型的判断if(typeof object === 'object'){
    //取出混入对象的每一个属性
    for(const key of 0bject. keys (object)){
    //如果属性所对应的值为对象继续递归调用mixinif(typeof object[key] === ' object'){
    target[key] = Array. isArray(object[key]) ? [] : {};mixin(target [key] , object [key]);}else{
    //否则就直接混入到目标对象里面
    0bject.ass ign(target , object);

    }
    }
    }
    激活Wii转到设置”

    }

     

  • 相关阅读:
    你必须会的 JDK 动态代理和 CGLIB 动态代理
    Dubbo 扩展点加载机制:从 Java SPI 到 Dubbo SPI
    volatile 手摸手带你解析
    Dubbo之服务消费原理
    Dubbo之服务暴露
    ElasticSearch之映射常用操作
    Redis5新特性Streams作消息队列
    .NET 开源项目 StreamJsonRpc 介绍[下篇]
    .NET 开源项目 StreamJsonRpc 介绍[中篇]
    .NET 开源项目 StreamJsonRpc 介绍 [上篇]
  • 原文地址:https://www.cnblogs.com/jrzqdlgdx/p/11267514.html
Copyright © 2011-2022 走看看