做者 | Jesksonhtml
来源 | 达达前端小酒馆前端
1web
到底是什么样的题目让我徒弟疑惑呢?让咱们看看截图先,来源于wx群:面试
看看我是怎么回答的:算法
function Foo() { getName = function () { alert (1); }; return this; } var getName; //只提高变量声明 function getName() { alert (5);} //提高函数声明,覆盖var的声明 Foo.getName = function () { alert (2);}; Foo.prototype.getName = function () { alert (3);}; getName = function () { alert (4);}; //最终的赋值再次覆盖function getName声明 getName(); //最终输出4
看懂没呢?没看懂也别急哈:segmentfault
先让咱们了解函数的定义:网络
函数声明,能够先调用再声明数据结构
dadaFn(); function dadaFn(){ console.log(dadaFn); }
/ 返回 f -> function function dadaFn() { console.log(dadaFn); }
let daDafn = function() { console.log("dada"); }; daDafn();
let fn = function() { console.log(111); } fn(); //111 VM1188:2 111 undefined let daDafn = function() { console.log("dada"); } daDafn(); VM1197:2 dada undefined
let da = () => {}; console.log( da.prototype );
JavaScript prototype属性,可让你向对象添加属性和方法:函数
格式:学习
object.prototype.name = value;
function dada (name,age) { this.name = name; this.age = age; } var dashu = new dada("dashucoding", 13); dada.prototype.job = null; dashu.job = it; console.log(dashu.jog);
输出结果:
it
let da1 = new Function('a', 'b'); da1(1,2);
let da1 = new Function('a', 'b'); da1(1,2); VM65:3 Uncaught ReferenceError: b is not defined at eval (eval at <anonymous> (local-ntp.html:1), <anonymous>:3:1) at <anonymous>:3:1 (anonymous) @ VM65:3 (anonymous) @ VM64:3 let fn1 = new Function('a', 'b', 'console.log(a * b)'); fn1(1, 2); //2 VM69:3 2 undefined
预解析,变量提高的概念:
function Foo() { getName = function () { console.log (1); }; return this; } Foo.getName = function () { console.log (2);}; Foo.prototype.getName = function () { console.log (3);}; var getName = function () { console.log (4);}; function getName() { console.log (5);} //请写出如下输出结果: Foo.getName(); getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName(); VM243:5 2 VM243:7 4 VM243:2 1 VM243:2 1 VM243:5 2 VM243:6 3 VM243:6 3
//答案: Foo.getName();//2 getName();//4 Foo().getName();//1 getName();//1 new Foo.getName();//2 new Foo().getName();//3 new new Foo().getName();//3
变量定义提高,this指针指向,运算符优先级
原型、继承、全局变量污染、对象属性及原型属性优先级
在JavaScript中,prototype对象是实现面向对象的一个重要机制。
每一个函数就是一个对象(Function),函数对象都有一个子对象 prototype对象,类是以函数的形式来定义的。prototype表示该函数的原型,也表示一个类的成员的集合。
经过new建立一个类的实例对象的时候,prototype对象的成员都成为实例化对象的成员。
一、该对象被类所引用,只有函数对象才可引用;
二、在new实例化后,其成员被实例化,实例对象方可调用。
同时,函数是一个对象,函数对象若直接声明成员,不用被实例化便可调用。
prototype 属性使您有能力向对象添加属性和方法。
构造函数的简单介绍
function Person(){ this.name = 'dada'; } var boy = new Person(); console.log(boy.name); //'dada' VM254:5 dada undefined
为了解决构造函数的对象实例之间没法共享属性的缺点,js提供了prototype属性。
js中每一个数据类型都是对象(除了null和undefined)。
每一个对象都继承自另一个对象,后者称为“原型”(prototype)对象,只有null除外,它没有本身的原型对象。
原型对象上的全部属性和方法,都会被对象实例所共享。
经过构造函数生成对象实例时,会将对象实例的原型指向构造函数的prototype属性。
每个构造函数都有一个prototype属性,这个属性就是对象实例的原型对象。
原型对象的属性不是对象实例的属性。
对于对象实例来讲,prototype是对象实例的原型对象。
因此prototype便是属性,又是对象。
原型链:原型链主要用于继承,每一个对象都有一个proto属性指向其构造函数的原型对象,当访问对象的属性和方法时,会先在对象自身进行查找,若是不存在,则沿着proto属性向上一级查找,直到没找到返回 undefined,这样的查找过程,称之为原型链。
原型链,请找我文章:一篇文章带你了解JavaScript中的变量,做用域,和内存问题。
function Foo() { getName = function () { console.log (1); }; return this; } Foo.getName = function () { console.log (2);}; Foo.prototype.getName = function () { console.log (3);}; var getName = function () { console.log (4);}; function getName() { console.log (5);} //请写出如下输出结果: Foo.getName(); // 2
看代码,先定义一个Foo()的函数,以后为Foo建立一个叫getName的静态属性,用来存储一个匿名的函数,以后为Foo的原型对象,新建立了一个叫getName的匿名函数。
var getName = function () { console.log (4);}; function getName() { console.log (5);}
而后经过函数变量表达式,建立一个getName的匿名函数,而后由经过函数变量表达式,建立一个getName的函数。
最后一个是声明一个叫getName的函数。
Foo.getName(); // 2
这个不用说就是访问Foo()函数上存储的静态属性,答为2。
下一个问:
getName(); Foo().getName(); getName(); new Foo.getName(); new Foo().getName(); new new Foo().getName();
getName(); 的答案呢? // 5 function Foo() { getName = function () { console.log (1); }; return this; } 这里要分开理解看 Foo.getName = function () { console.log (2);}; Foo.prototype.getName = function () { console.log (3);}; var getName = function () { console.log (4);}; function getName() { console.log (5);}
function Foo() { getName = function () { alert (1); }; return this; } var getName; //只提高变量声明 function getName() { alert (5);} //提高函数声明,覆盖var的声明 Foo.getName = function () { alert (2);};
getName = function () { alert (4);}; //最终的赋值再次覆盖function getName声明 getName(); //最终输出4
var getName 只提高变量声明
function getName 函数声明,覆盖var的声明
直接调用getName()函数,就是访问当前上文做用域内的叫getName的函数
这样var getName提高,函数总体提高到上面了,那么就剩下getName结果为4的那个了。
一个是变量做用域问题,一个是this指向问题。
Foo().getName();
第一个Foo()函数:
function Foo() { getName = function() { console.log('1'); } }
即Foo().getName()中
先执行Foo()函数,而后调用Foo函数返回的返回值对象的getName属性函数。
getName(); // 函数 1
至关于window.getName(),由于这个变量被Foo函数执行时修改了,结果一样为1。
new Foo.getName();
点 . 的优先级高于new操做,等价于:
new (Foo.getName)(); // 将getName函数做为了构造函数来执行 // 2
new Foo().getName(); // 3 // 运算符优先级括号高于new 等价于 (new Foo()).getName()
先执行Foo函数,此时做为构造函数,有返回值。
如有返回值则检查其返回值是否为引用类型
若返回值是引用类型,则实际返回值为这个引用类型。
价于 (new Foo()).getName() # ``` 
new new Foo().getName();
new ((new Foo()).getName)();
// 3
## ❤️ 不要忘记留下你学习的脚印 [点赞 + 收藏 + 评论] 做者Info: > 【做者】:Jeskson > 【原创公众号】:达达前端小酒馆。 > 【福利】:公众号回复 “资料” 送自学资料大礼包(进群分享,想要啥就说哈,看我有没有)! > 【转载说明】:转载请说明出处,谢谢合做!~ 大前端开发,定位前端开发技术栈博客,PHP后台知识点,web全栈技术领域,数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。谢谢支持,承蒙厚爱!!! ---- 若本号内容有作得不到位的地方(好比:涉及版权或其余问题),请及时联系咱们进行整改便可,会在第一时间进行处理。 ---- ## 请点赞!由于大家的赞同/鼓励是我写做的最大动力! ### 欢迎关注[达达](https://blog.csdn.net/qq_36232611)的CSDN! **这是一个有质量,有态度的博客**