1、普通函数
- 堆栈内存
- 作用域链
2、类(构造函数)
- prototype 原型
__proto__
原型链- 实例
3、普通对象
- 和普通的obj没啥区别,就是对键值对的增删改查
三种角色没有必然关系
1、私有变量只跟普通函数有关
,在作为类和普通对象情况下是没用的(获取不到)
2、prototype是函数作为普通对象的一个属性,但是prototype里边放的东西就跟它就没关系了而是跟它的实例有关系;
3、凡是Fn.prototype.xxx=xxx都是跟作为构造函数创建出来的实例有关
4、在new Fn()的方式中,函数体中的this.xxx=xxx 都是跟作为构造函数创建出来的实例有关
5、作为普通对象时,只有 Fn.属性名=属性值 这种才和它有关系
6、函数体中的代码跟作为普通对象没关系,因为函数体中放的是字符串,不执行一点意义也没有,而作为对象不需要执行就能操作键值对
7、new xxx也会使函数执行
function Fn(){
var n=10;
this.m=100;
}
Fn.prototype.aa=function(){
console.log('aa')
}
Fn.bb=function(){
console.log('bb')
}
//=>普通函数的执行
Fn(); //this:window 有一个私有变量 n ; 和原型以及属性没有关系
//=>构造函数执行
var f=new Fn(); //this:f
console.log(f.n) //undefined n为私有变量 和实例没有关系
console.log(f.m) //100 实例的私有属性
f.aa(); //'aa' 通过原型链找到了 Fn.prototype上的方法
f.bb(); //bb is undefined bb是把Fn当做一个普通对象设置的属性而已;和实例等没有半毛钱关系
//=>普通对象 只跟Fn.bb有关 prototype是函数对象的一个属性,但是prototype里边放的东西跟它就没关系了
Fn.bb() //'bb'
以Number内置类为例:
console.dir(Number)
把Number作为普通对象加入的方法,点前边必须为Number
Number的prototype里存的方法是实例的方法,所以点前边必须是Number的具体实例才能调用(数字或者NaN)
jQuery这个类库中提供了很多的方法,其中有一部分是写在原型上的,有一部分是把它当做普通对象来设置的
~function (){
function jQuery(){
//...
//return [jQuery实例]
}
jQuery.prototype.animate=function (){}
jQuery.ajax=function(){}
window.jQuery = window.$ =jQuery;
}();
$(); //返回实例
$().ajax() //不能调用,ajax是普通对象的键值对
$.ajax() //可以 直接调取普通对象键值对
$().animate() //可以
$.animate() //不可以 对象上没有animate这个属性
var getName=function(){},在全局变量提升中只是定义 没赋值,getName为undefined,在代码执行的时候才赋值;function getName 声明并赋值全局 getName 为‘console.log(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(5)的函数顶掉
console.log(4)
}
function getName(){ //全局变量提升阶段声明并定义 代码执行的时候就不再进行任何操作
console.log(5)
}
Foo.getName(); // 2
getName(); //4
Foo().getName(); // 1
getName(); //1
new Foo.getName(); //=>A:(Foo.getName) =>new A; 2
new Foo().getName() //=>B:new Foo() =>B.getName() 3
new new Foo().getName(); //=>C:new Foo() =>把C.getName作为一个整体new(C是Foo的实例) D:C.getName => new D() 3
//=>全局作用域
//变量提升 Foo,getName
//Foo=AAAFFF111(1、开辟堆内存2、存字符串3、建立联系)天生自带 prototype
//getName=AAAFFF222(1、开辟堆内存2、存字符串3、建立联系)天生自带 prototype
//var getName=,在全局变量提升中只是定义 没赋值;function getName 声明并赋值全局 getName 为‘console.log(5)’ **重要注意点**
//=>代码执行
//AAAFFF111.getName=bbbFFF111 console.log(2) Foo作为普通对象添加键值对
//AAAFFF111.prototype.getName=bbbFFF222 console.log(3)
//var getName=, 因为在变量提升中声明过所以只赋值;所以全局getName为‘console.log(4)’
//Foo作为普通对象的getName执行 2
//全局getName(window.getName)执行 4
//Foo作为普通函数执行,把返回值的getName执行
//Foo作为普通函数执行形成私有作用域
//形参赋值 变量提升没有
//代码执行
//全局getName console.log(1)
//return this 为 window
//window.getName执行 1
//全局getName(window.getName)执行 1
//(new (Foo.getName))() Foo作为普通对象的getName属性 执行 2
//(new Foo()).getName() 实例.getName执行 3
//(new ((new Foo()).getName))() (实例.getName)的实例 执行 3
在Foo后面没有东西的时候,new Foo和new Foo()是一样的;但是在Foo后面有东西时就不一样了:new Foo.getName() 是把new Foo.getName作为一个整体new的 相当于A:(Foo.getName) new A;new Foo().getName() 先new Foo() 让实例的getName执行
js中的运算符优先级 (数值越大优先级越高)
从左到右:同级别 从左到右先写谁,谁的优先级高
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!