对象与原型对象下篇



迷途 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转到设置”

}

 

原文地址:https://www.cnblogs.com/jrzqdlgdx/p/11267514.html