网络初级2

目录

1、this

1.1注意点

1.2适用场景

(1).全局环境

(2).构造函数

(3).对象的方法

2.对象的继承

2.1prototype 属性的作用

2.2原型链

2.3constructor 属性

2.4构造函数的继承

2.5多重继承

1、this

1.1注意点

        1.this始终指向调用该函数的对象;

        2.若没有指明调用的对象,则顺着作用域链向上查找,最顶层为global(window)对象;

        3.箭头函数中的this是定义函数时绑定的,与执行上下文有关

        4.简单对象(非函数、非类)没有执行上下文;

        5.类中的this,始终指向该实例对象;

        6.箭头函数体内的this对象,就是定义该函数时所在的作用域指向的对象,而不是使用时所在的作用域指向的对象。

        7.避免多层this的出现

1.2适用场景

(1).全局环境
this === window // true

function f() {
  console.log(this === window);
}
f() // true

不管是不是在函数内部,只要是在全局环境下运行,this就是指顶层对象window

(2).构造函数
var Obj = function (p) {
  this.p = p;
};


var o = new Obj('Hello World!');
o.p // "Hello World!"

由于this指向实例对象,所以在构造函数内部定义this.p,就相当于定义实例对象有一个p属性。

(3).对象的方法

        如果方法里面包含this,this指向的是方法运行是所在的对象,如果该方法给另一个对象,就会改变this的指向。

var obj ={
  foo: function () {
    console.log(this);
  }
};

obj.foo() // obj

// 情况一
(obj.foo = obj.foo)() // window
// 情况二
(false || obj.foo)() // window
// 情况三
(1, obj.foo)() // window

上三种代码 等同于

​
// 情况一
(obj.foo = function () {
  console.log(this);
})()
// 等同于
(function () {
  console.log(this);
})()

// 情况二
(false || function () {
  console.log(this);
})()

// 情况三
(1, function () {
  console.log(this);
})()

​

this所指的方法如果不在这第一层,这时候this就只是指向当前一层的对象,不回去继承上一层。

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined

a.b.m的方法在a对象的第二层,所以他内部的this就是指的a.b,相当于

var b = {
  m: function() {
   console.log(this.p);
  }
};

var a = {
  p: 'Hello',
  b: b
};

(a.b).m() // 等同于 b.m()

2.对象的继承

面向对象编程很重要的一个方面,就是对象的继承。A 对象通过继承 B 对象,就能直接拥有 B 对象的所有属性和方法。这对于代码的复用是非常有用的。

大部分面向对象的编程语言,都是通过“类”(class)实现对象的继承。传统上,JavaScript 语言的继承不通过 class,而是通过“原型对象”(prototype)实现。

2.1prototype 属性的作用


JavaScript 继承机制的设计思想就是,原型对象的所有属性和方法,都能被实例对象共享。也就是说,如果属性和方法定义在原型上,那么所有实例对象就能共享,不仅节省了内存,还体现了实例对象之间的联系。

下面,先看怎么为对象指定原型。JavaScript 规定,每个函数都有一个prototype属性,指向一个对象。

function f() {}
typeof f.prototype // "object"

上面代码中,函数f默认具有prototype属性,指向一个对象。

对于普通函数来说,该属性基本无用。但是,对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。

构造函数的一个方法,或者一个属性

function Animal(name) {
  this.name = name;
}
Animal.prototype.color = 'white';
 
var cat1 = new Animal('大毛');
var cat2 = new Animal('二毛');
 
cat1.color // 'white'
cat2.color // 'white'


 上面代码中,构造函数Animal的prototype属性,就是实例对象cat1和cat2的原型对象。原型对象上添加一个color属性,结果,实例对象都共享了该属性。

2.2原型链


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

a---->b------>c------>d-------->Object

如果一层层地上溯,所有对象的原型最终都可以上溯到Object.prototype,即Object构造函数的prototype属性。也就是说,所有对象都继承了Object.prototype的属性。这就是所有对象都有valueOf和toString方法的原因,因为这是从Object.prototype继承的。

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

Object.getPrototypeOf(Object.prototype)
// null


2.3constructor 属性


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

function P() {}
P.prototype.constructor === P // true
 由于constructor属性定义在prototype对象上面,意味着可以被所有实例对象继承。

function P() {}
var p = new P();
 
//应该有这个属性吗
p.constructor === P // true
 
p.constructor === P.prototype.constructor // true
 
p.hasOwnProperty('constructor') // false


上面代码中,p是构造函数P的实例对象,但是p自身没有constructor属性,该属性其实是读取原型链上面的P.prototype.constructor属性。

2.4构造函数的继承


 让一个构造函数继承另一个构造函数,是非常常见的需求。这可以分成两步实现。第一步是在子类的构造函数中,调用父类的构造函数。

function Sub(value) {
  Super.call(this);
  this.prop = value;
}


上面代码中,Sub是子类的构造函数,this是子类的实例。在实例上调用父类的构造函数Super,就会让子类实例具有父类实例的属性。

第二步,是让子类的原型指向父类的原型,这样子类就可以继承父类原型。

Sub.prototype = Object.create(Super.prototype);
Sub.prototype.constructor = Sub;
Sub.prototype.method = '...';


上面代码中,Sub.prototype是子类的原型,要将它赋值为Object.create(Super.prototype),而不是直接等于Super.prototype。否则后面两行对Sub.prototype的操作,会连父类的原型Super.prototype一起修改掉。

2.5多重继承


JavaScript 不提供多重继承功能,即不允许一个对象同时继承多个对象。但是,可以通过变通方法,实现这个功能。

function M1() {
  this.hello = 'hello';
}
 
function M2() {
  this.world = 'world';
}
 
function S() {
  M1.call(this);
  M2.call(this);
}
 
// 继承 M1
S.prototype = Object.create(M1.prototype);
// 继承链上加入 M2
Object.assign(S.prototype, M2.prototype);
 
// 指定构造函数
S.prototype.constructor = S;
 
var s = new S();
s.hello // 'hello'
s.world // 'world'
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值