JS 实例对象与New命令、原型对象、constructor属性、instanceof运算符、构造函数的继承、多重继承、Object对象

1、实例对象与New命令

(1)new命令的原理

若构造函数内部有 return 语句,并且 return 语句返回一个对象,new 命令会返回这个 return 语句,否则就会不管这个 return语句,返回 this 对象。

若return 语句返回的是跟 this 无关的对象,new 命令会返回这个新对象,而不是 this 对象。

若是内部没有 this 的普通构造函数使用 new 命令,则会返回一个空对象。

//例 1
var Vehical = function (){
   this.price = 1000;
   return 2000;
};

(new Vehical()) === 2000;  //false


//例2
var Vehical = function(){
   this.price = 1000;
   return {price:2000;}
};

(new Vehical()).price ;  //2000


//例3
function getMessage(){
   return "This is a message";
}

var msg = new getMessage();
msg  ; //{}
typeof msg ;//object

(2)this:简单地说, this 就是属性或方法 “当前”所在的对象。

(3)绑定 this 的方法

Function.prototype.call():参数可以指定函数内部 this 的指向(即函数执行时所在的作用域),然后在该作用域下调用该函数。该参数应为对象,若该参数是 null,undefined 或为空,则默认传入全局对象。若该参数为原始值,则该值会被转换成对象。

//例 1
var obj = {};

var f = function(){
    return this;
};

f() === window   //true
f.call(obj) === obj  //true

//例 2
var n = 123;
var obj = {n:456};

var f = function(){
    return this.n
};

f.call()            //123
f.call(null)        //123
f.call(undefined)   //123
f.call(window)      //123
f.cal(obj)          //456

Function.prototype.apply():与 call()类似,参数也是指定函数运行时 this 的作用域,但是它的第一个参数是 this 要指向的对象,第二个参数是数组。

apply()最重要的作用是将对象转换为数组,对象须具有 length 属性

Array.prototype.slice.apply({0:1,length:1});  //[1]
Array.prototype.slice.apply({0:1});           //[]
Array.prototype.slice.apply({0:1,length:2});  //[1,undefined]
Array.prototype.slice.apply({length:1});      //[undefined]

Function.prototype.bind():用于将函数体内的 this 绑定到某个对象,然后返回一个新的函数。

var d = new Date();
d.getTime();   // 1481869925657

var print = d.getTime();
print();       //Uncaught TypeError: this is not a Date object.

若改为  var print = d.getTime.bind(d);
print();       // 1481869925657

2.原型对象定义所有实例对象共享的属性和方法。

对于构造函数来说,生成实例的时候,该属性会自动成为实例对象的原型。原型对象的属性不是实例对象自身的属性,只要修改原型对象,变动就会立刻体现在所有实例对象上。

function Animal(name){
    this.name = name;
}

Animal.prototype.color = "black";

var cat = new Animal("小猫");
var dog = new Animal("小狗");

cat.color  //"black"
dog.color  //"black"

若是实例对象自身就有某个属性或方法,它就不会再去原型对象再找这个属性或方法了。

Animal.prototype.color = "yellow";

cat.color = "white";

cat.color   //"white"
dog.color   //"yellow"

3.constructor属性:

(1)可以得知某个实例对象,到底是哪一个构造器产生的。

function F (){};
var f = new F();

f.constructor === F;  //true
f.constructor === RegExp;  //false

(2)有了 constructor 属性,就可以从一个实例对象新建另一个实例。

//1
function Constr(){};
var x = new Constr();

var y = new x.constructor();

y instanceof Constr  // true

//2
Constr.prototype.createCopy = function(){
    return new this.constrcutor();
};
//createCopy 方法调用构造函数,新建另一个实例。

(3)constructor 表示原型对象与构造函数之间的关联关系,若修改原型对象,则同时修改 constructor 属性,不然会报错。

function Person(name){
  this.name = name;
}

Person.prototype.constructor === "Person"  //true

Person.prototype ={
   methon:function() {}
};

Person.prototype.constructor ==="Person"  //false
Person.prototype.constructor === "Object"  //true

共有两种修改方法

//方法1
C.prototype = {
    constructor:C,
    method:function(){}
};


//方法2  方法2 更好

C.prototype.method = function(){};

4.instanceof运算符:返回一个布尔值,表示对象是否为某个构造函数的实例(原理是检查右边的实例对象,是否在左边对象的原型链上)。instanceof 只适用于对象,不适用于原始类型的值。

var v = new Vehical();

v instanceof Vehical;  //true

//等同于

Vehical.prototype.isPrototypeOf(v);  //true

(1)由于 instanceof 检查整个原型链,因此同一个实例对象可能会对多个构造函数都返回 true。

var d = new Date();

d instanceof Date;  //true
d instanceof Object;//true

(2)由于除了 null 之外,任意对象都是 Object 的实例,所以用 instanceof可以判断一个值是否为非 null 对象。

var obj = {foo:123};

obj instanceof Object;  //true
null instanceof Object; //false

(3)有一种特殊情况,当左边对象的原型链上只有 null 时,instanceof 判断就会失真。

var obj = Object.create(null);

typeof obj ;  //Object
Object.create(null) instanceof Object //false

5.构造函数的继承

第一步:在子类的构造函数中,调用父类的构造函数

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

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

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

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

另一种方法如下,但是这样子类会有父类实例的方法,所以这种用法我们不推荐。

Sub.prototype = new Super();

有时需要继承父类构造器里的单个方法,则

ClassB.prototype.method1 = {
   ClassA.prototype.method1.call(this);
   ...
};

6.多重继承:JS里边不支持多重继承,但是可以通过别的方法使其具有多重继承的功能

function M1(){
   this.hello = "hello";
}

function M2(){
   this.world = "world";
}

function S(){
   M1.call(S);
   M2.call(S);
}

S.prototype = Object.create(M1);//继承 M1
Object.assign(S.prototype,M2.prototype);//继承链上加上 M2

S.prototype.constructor = S;  //指定构造函数

var s = new S();
s.hello  //"hello"
s.world  //"world"

7.Object对象

(1)获取对象原型的三种方法

方法一:obj._proto_ ,只有浏览器才需要部署,其他情况下不需要

方法二:obj.prototype.constructor,在手动改变原型数据时,可能会失效

方法三:Object.getPrototypeOf(obj)  ,这种方法最好

(2)hasOwnProperty() ,用于判断某个对象属性是定义在对象自身,还是定义在原型链上。还是此方法是 JS 中唯一一个处理原型对象属性时,不需要遍历链的方法

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值