今天来说一下js面向对象的小练习,废话不多说直接上练习,如果你能做出这个练习,说明你对js对象的一些知识已经很清晰了
一、代码
function Foo(){
getName = function(){
alert(1);
};
return this;
}
Foo.getName = function (){alert(2);};
Foo.prototype.getName=function () {alert(3);};
var getName = function (){ alert(4);};
function getName(){alert(5);}
// 写出下面的结果
// 1 Foo.getName();
// 2 getName();
// 3 Foo().getName();
// 4 new Foo.getName();
// 5 new Foo().getName();
// 6 new new Foo().getName();
怎么样你已经知道答案了么?
二、具体分析
1.Foo.getName(); 结果 弹出 2
分析:这个应该很简单,直接执行Foo.getName 函数表达式。
2.getName(); 结果 4 ,这个不难
分析:这里有一些知识点,我来详细的说一下,
① 当变量名字(没有赋值的情况下)和 函数名相同时,优先读取函数,也就是:
var getName
function getName(){alert(5);}
getName(); //结果会是5
3.Foo().getName(); 结果 1
这一块知识点比较多,我们来慢慢分析。
Foo() 函数执行完时,因为Foo()函数中返回了this, 当执行完时,Foo函数内的数据就暴露在了全局环境下,所以 返回的this 也就是Foo()指的是window,
那么你可能会说 在window下getName 函数有两个呀
getName = function(){
alert(1);
};
var getName = function (){ alert(4);};
为啥不弹出 4, 原因在于var声明的变量被提升了,而 没有用var声明的变量没有被提升(属于全局变量),其次,函数中如果用var 声明的变量,它的作用域是在函数内的,这里没有用var 声明getName 函数表达式,所以Foo().getName() 结果为1 ;
4.new Foo.getName(); 结果 2
这个结果不知道你有没有想对,对于这个结果首先我们需要知道 new 操作符背后做了些什么。可以看一看我以前的文章http://blog.csdn.net/webxiaoma/article/details/65937768
其实在用new 操作符创建对象时,它背后给我们做的一些工作类似于:
var obj1= (function(){
var o={}; //创建一个新对象
o.__proto__=obj.prototype; //将新对象的原型链指向obj的原型
obj.call(o,"hello") //执行obj函数,将o对象指针指向obj函数,及o拥有了obj原型的属性和方法(引用)
return o;
})()
这里new 出来的构造函数,会继承实例的原型上边的所有属性和方法。
这里弹出来的是 2 ,的原因是
① new操作符在执行时,执行了call 函数(或者apply函数),Foo.getName()
在new 创建对象时,在其内部执行了。你这里这样写new Foo.getName
也会弹出 2;
②这里生成的构造函数是Foo.getName
的构造函数,如果你不信,可以自己手动为Foo.getName的原型添加一个属性或方法(例如: Foo.getName.prototype.name = 4;),然后让后利用创建的构造函数去访问。
var ac = new Foo.getName();
console.log(ac.name) // 4
5.new Foo().getName(); 结果是 3;
如果你上边的结果看懂了,那么这个你将很容易明白。这里和上边的唯一区别就是 函数 Foo 加了括号,这这个区别就改变了构造函数的实例,上边构造出来的函数的实例是Foo.getName
,而这个构造函数的实例是 Foo
函数。
这里 new Foo().getName();
的写法 其实就相当于:
var a = new Foo();
a.getName();
好了以上就是我分析的过程,如果有什么错误或问题,欢迎留言。