目录
P15 15.尚硅谷_JS高级_函数的prototype 15:04
P16 16.尚硅谷_JS高级_显式原型与隐式原型 28:34
P19 19.尚硅谷_JS高级_原型链_属性问题 11:53
P20 20.尚硅谷_JS高级_探索instanceof 20:23
P22 22.尚硅谷_JS高级_变量提升与函数提升 10:02
P15 15.尚硅谷_JS高级_函数的prototype 15:04
函数的prototype属性
- 每个函数都有一个prototype属性,它默认指向一个Object空对象(即成为:原型对象)
- 原型对象中有一个属性:constructor,它指向函数对象
给原型对象添加属性(一般都是方法)
- 作用:函数的所有实例对象自动拥有原型中的属性(方法)
- 我自己的理解就是,原型对象类似于组件,修改组建,所有实例也一样修改
构造函数和原型对象相互引用
![]()
P16 16.尚硅谷_JS高级_显式原型与隐式原型 28:34
- 每个函数function都有一个prototype,即显式原型
- 每个实例对象都有一个__proto__,即隐式原型
- 对象的隐式原型的值为其对应构造函数的显式原型的值
- 内存结构(图)
- 总结
- 函数的prototype属性:在定于函数时自动添加的,默认值是一个空Object对象
- 对象的__proto__属性:创建对象时自动添加的,默认值为构造函数的prototype属性值
- 程序员能直接操作显式原型,但不能直接操作隐式原型(ES6之前)
第4点的图示
重点总结:实例对象的隐式原型都指向构造函数的显示原型
P17 17.尚硅谷_JS高级_原型链 44:34
1.原型链(图解)
- 访问一个对象的属性时,
- 先在自身属性中查找,找到返回
- 如果没有,再沿着__proto__这条链向上查到,找到返回
- 如果最终没找到,返回undefined
- 别名:隐式原型链
- 作用:查找对象的属性(方法)
2.构造函数/原型/实体对象的关系(图解)
3.构造函数/原型/实体对象的关系(图解2)
所有函数的__proto__都是一样的
P18 18.尚硅谷_JS高级_原型链_补充 10:29
- 函数的显示原型指向的对象默认是空Object实例对象(但Object不满足)
- 所有函数都是Function的实例 (包括Function)
//true
- Object的原型是原型链尽头
P19 19.尚硅谷_JS高级_原型链_属性问题 11:53
读取对象的属性值时:会自动到原型链中查找
设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
P20 20.尚硅谷_JS高级_探索instanceof 20:23
1.instanceof是如何判断的?
- 表达式:A instanceof B
- 如果B函数的显式原型对象在A对象的原型链上,返回true,否则返回false
案例1
<script> function Foo() { }; var f1 = new Foo(); console.log(f1 instanceof Foo);//true console.log(f1 instanceof Object);//true </script>
案例2
console.log(Object instanceof Function); //true console.log(Object instanceof Object); //true console.log(Function instanceof Function); //true console.log(Function instanceof Object); //true function Foo() { }; console.log(Object instanceof Foo); //false
2.Function是通过new自己产生的实例
P21 21.尚硅谷_JS高级_原型_面试题 19:15
案例1
案例2
看上面图解
只有f.b()输出 undefined
P22 22.尚硅谷_JS高级_变量提升与函数提升 10:02
1、变量声明提升
- 通过var定义(声明)的变量,在定义语句之前就可以访问到
- 值:undefined
面试题:输出 undefined
<script> var a = 3 function fn() { console.log(a); } fn()//3 </script>
这样写,输出3,正常执行
<script> var a = 3 function fn() { console.log(a); var a = 4 } fn() //undefined </script>
函数执行,先从内部执行,var a =4,执行顺序是,先在函数内部声明了a:var a,但是没有赋值,即输出,最后才赋值:a = 4,因此输出undefined,如图所示
<script> var a = 3 function fn() { var a; console.log(a); a = 4 } fn() //undefined </script>
2、函数声明提升
- 通过function声明的函数,在之前就可以直接调用
- 值:函数定义(对象)
fn3属于变量提升,因此不能提前调用
3、问题:变量提升和函数提升是如何产生的
P23 23.尚硅谷_JS高级_执行上下文 21:48
1.代码分类(位置)
- 全局代码
- 函数(局部)代码
2.全局执行上下文
- 在执行全局代码前将window确定为全局执行上下文
- 对全局数据进行预处理
- var定义的全局变量==>undefined,添加为window的属性
- function声明的全局函数==>赋值(fun),添加为window的方法
- this==>赋值(window)
- 开始执行全局代码
- 只能存在一个
3.函数执行上下文
- 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象(虚拟的,存在于栈中)
- 对局部数据进行预处理
- 形参变量==>赋值(实参)==>添加为执行上下文的属性
- arguments==>赋值(实参列表),添加为执行上下文的属性
- Var定义的局部变量==>undefined,添加为执行上下文的属性
- func声明的函数==>赋值(fun),添加为执行上下文的方法
- this==>赋值(调用函数的对象)
- 开始执行函数体代码
注意:函数不调用就不会创建 函数执行上下文
P24 24.尚硅谷_JS高级_执行上下文栈 17:25
- 在全局代码执行前,JS引擎就会创建一 个栈来存储管理所有的执行上下文对象
- 在全局执行上下文(window)确定后, 将其添加到栈中(压栈)
- 在函数执行上下文创建后,将其添加到栈中(压栈)
- 在当前函数执行完后,将栈顶的对象移除(出栈)
- 当所有的代码执行完后,栈中只剩下window
至多存在N+1个执行上下文
f1()
f2()
f3()
//至多存在3个(2个函数执行上下文+1个全局执行上下文)
//因为执行f3的时候,f2执行结束将会被释放
f1(){
f2(){
f3(){
}
}
}
//至多存在4个(3个函数执行上下文+1个全局执行上下文)
P25 25.尚硅谷_JS高级_面试题 19:49
<script> console.log('gb:' + i); var i = 1; foo(1); function foo(i) { if (i == 4) { return } console.log('fb:' + i); foo(i + 1) console.log('fe:' + i); }; console.log('ge:' + i); //undefined gb:1 fb:2 fb:3 fe:3 fe:2 fe:1 ge:1 </script>
原因:c不是个函数,真正执行过程