关于JS中的函数(类),成员,prototype(__proto__)

函数

Javascript中的函数除了本身作为一个函数之外还有三个身份:

  • 作为Funcation类的对象
  • 作为自身类的构造函数
  • 作为一个实实在在的类

先说作为Funcaton类的实例这种情况,可以用instanceof去检测:
在这里插入图片描述
查看控制台可以发现:
在这里插入图片描述
说明它确实是Funcation的一个实例

再来说剩下的两种情况,看下面的例子:
在这里插入图片描述
查看控制台:
在这里插入图片描述
首先,我们说在java中或者C++中,都有构造函数,new的实质就是创造一个该类的实例,是需要调用该类的构造方法,从结果可以看出来,首先,我们只是new了一下a,没有报语法错误,却执行了a中的代码,说明它不仅是一个类,而且是本类的构造方法! 其次如果它是一个类,som就是它的一个实例,也就是一个对象,检测som,发现他就是一个object{}对象!,其次 instanceof也检测出来som是a的一个实例。

成员

在JS中,var 就是定义一个变量,那么看下面的例子;
在这里插入图片描述
在这里插入图片描述
可以看出var 如果定义在函数内部,就是函数的局部变量,如果定义在外面,就是Window类的成员,如果在函数内部没加修饰符定义的变量,就认为是Window类的成员,如果加this的话就认为是该函数的成员。

关于__proto__

每一个类都有这个成员(在火狐中是prototype,这里用火狐浏览器演示),可以这样认为,这个成员里存的东西就是类的一个静态成员,如果大家有静态的概念的话这里很好理解,如果没有的话建议自行百度什么是静态,后面说的会有点难度,看下面这段代码:
在这里插入图片描述
在这里插入图片描述首先我们定义了一个point类,里面还有一个函数成员,然后p1是它的实例,请注意prototypeMember,这是我们代码里直接通过point.prototype.prototypeMember = prototypeMember赋值的,这个prototypeMember我们可以看成是类的静态成员,那么他的调用和赋值就可以直接使用 (类.prototype.成员) 来调用 , 直接使用p1.prototypeMember = 250 就相当于给p1增加了一个成员,赋值为250,它和point类里面的prototype里面的prototypeMember没有关系,如果我们想通过实例p1实现对point类中的所谓的静态成员进行修改,怎么办呢?有一个保留方法,就是p1.__proto__.prototypeMember,这也可以赋值,但是不建议使用,如果使用不当会带来很大的麻烦,看下面的例子:

var Point = function (_row, _col) {
	this.row = _row;
	this.col = _col;
	this.moveTo = function (row, col) {
		this.row = row;
		this.col = col;
	};
};

var complex = function(){};
var p1 = new Point;
console.log(p1 instanceof Point);  //true
p1.__proto__ = complex.prototype;
console.log(p1 instanceof Point);  //false
console.log(p1 instanceof complex);  // true


上述这是很麻烦的问题,从这里也可以推测,prototype成员就是用来鉴别某个对象是否是某个类的实例,所以说避免使用如上的这种方法。
还有一个很有趣的事情,看下面的代码:

console.log(num);
var fun = function () {
	console.log("abc:", abc);  //abc:Undenfined
	var abc = 10;
};

fun();

如果我们直接执行第一行的代码,会报错,提示num未定义,但是看下面的代码,我们定义了一个函数,先输出了abc,按理说此时它还没有定义,应该也提示未定义错误,但是结果不是这样,而是提示undefined,为什么是这样呢,这里涉及到浏览器对js代码的解析,它其实是二次解析;第一次,先扫描有没有var,funcation等等之类的定义,将其值赋值为Undenfined;第二次才开始逐行阅读代码,进行相应的操作;所以会出现上面的情况,如果还不清楚的话我们还可以做一个实验,代码如下:

console.log("o:", o); 
var o = {};
o.abc = 100;
console.log("o:", o);
o.xyz = 123;
console.log("o:", o);

在这里插入图片描述
结果说明我们之前的说法完全正确,就是先检测var之类的定义,然后再逐行执行代码,但是这儿有个很有趣的现象,如果我们点击第二行的那个小三角的话,会出现如下:
在这里插入图片描述
???什么情况,刚才说的都是错的吗?? 冷静老弟,刚才说的都是正确的,在这儿点击小三角可以认为就是查看o{}这个对象的成员,在你点击的一瞬间就显示出来了所有的成员,而在一开始你输出的时候,那个时候还不存在xyz这个成员呢! 有人或许会问,那么第一行为啥不是?老弟,第一行是Undenfined啊,它根本没有点击小三角的机会啊!!!

有一个很奇怪的东西,或者说有驳常理的东西,大家都知道instanceof是用来判断,一个对象是不是一个类的实例,那么下面的代码就很怪了:

Function instanceof Object;//true
Object instanceof Function;//true

怎么会出现一个对象既是一个类的实例,同时它也是一个实例对象的元类呢?
下面这个图就很好的解释了这个问题,根据之前的说法,每个对象都有一个__proto__的属性,它指向了它的元类的prototype属性,这里出现了一个匿名类作为一个中转类,用来处理这个问题,object的__proto__成员指向了Function的prototype,而Function的__proto__成员指向了一个匿名类,而这个匿名类的__proto__指向了object的prototype,这就导致了之前的结果,下面的图可以看得很清楚:
在这里插入图片描述

补充:
关于__proto__以及prototype,或者说被称为原型链的东西,
以下的文章中有详细讲解:传送门1 传送门2

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值