js第二天学习整理

115 阅读6分钟
1、原型与原型链

每个函数都有一个prototype属性,默认指向一个空的Object对象(原型对象)

原型对象有一个属性constructor,指向函数对象。

image.png

//原型对象中有一个constructor 对象指向函数对象
consoloe.log(Data.protype.constructor === Data)

//给原型对象添加属性(方法)一般是给实例对象使用的
function Fun(){
    
}

Fun.protype.test = function(){ console.log('tianze')}
 
let fun = new Fun()
fun.test();//tianze


显示原型与隐式原型

1、函数都有一个prototype 属性(显示原型)=>定义函数时自动添加,默认为空的Object对象

2、实例对象都有一个__porto__属性(隐示原型)=>创建对象时自动添加,默认为构造函数的prototype属性

3、对象的隐式原型值对应其构造函数的显示原型的值

function Fun(){}  //内部执行语句=> Fun.prototype = {}
let fn = new Fun();//内部执行语=> this.__proto__ = Fun.prototype
console.log(fn)
console.log(Fun.prototype===fn.__proto__) //true

image.png


原型链
1、访问对象的属性时,先在自身属性查找,找到返回
未找到就沿着__proto__这条链查找找到返回,如果没有找到返回undefined

image.png

image.png

(待补充......)

作用域链

1、作用域:

      (1)所有末定义直接赋值的变量自动声明为拥有全局作用域
      (2)所有window对象的属性拥有全局作用域(全局访问)
      (3)在一个js文件可能会写好多个js模块,一些模块没有进行块级作用域操作就会污染全局变量
      书写方式;(function(){//js模块})();

2、函数作用域

     (1)指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。
     (2)内层作用域可以访问外层作用域,反之则不行
     (3)块语句(大括号“{}”中间的语句),如 if 和 switch 条件语句或 for 和 while 循环语句,不像函数,它们不会创建一个新的作用域

3、块级作用域

    (1)let和const声明,所声明的变量在指定块的作用域外无法被访问.一个{}就是一块(太爽了)
    (2)let /const 声明变量不会提升到代码块顶部(先声明在使用、不能重复命名=>用得都舒服多了)
    (3)重点就是for循环得变量设置

4、作用域链

//自由变量:当前作用域没有定义此变量,但是对此变量进行操作了
//作用域链:当前作用域没有就会向上一层找
var a = 100
function F1() {
    var b = 200
    function F2() {
        var c = 300
        console.log(a) // 自由变量,顺作用域链向父作用域找
        console.log(b) // 自由变量,顺作用域链向父作用域找
        console.log(c) // 本作用域的变量
    }
    F2()
}
F1()
function fn() {
  console.log(x)
}
function show(f) {
  var x = 20
  (function() {
    f() //10,而不是20
  })()
}
show(fn)
个人理解:
函数的作用域,在定义时就已经确定了,而不是在再里层得作用域一层一层得查找。
他的理解:
要到创建这个函数的那个域”。 作用域中取值,这里强调的是“创建”,
而不是“调用”,切记切记——其实这就是所谓的"静态作用域"
var a = 10
function fn() {
  var b = 20
  function bar() {
    console.log(a + b) //30
  }
  return bar
}
var x = fn(),
  b = 200
x() //bar()
fn()返回的是bar函数,赋值给x。执行x(),即执行bar函数代码。取b的值时,
直接在fn作用域取出。取a的值时,试图在fn作用域取,但是取不到,
只能转向创建fn的那个作用域中去查找,结果找到了,所以最后的结果是30

探索instanceof

A instanceof B 是如何判断的A 是 B 的三实例对象

如果B函数的显示原型对象在A对象的原型链上,就返回true 否则就返回 false

image.png

实例对象的隐式原型指向函数的显示原型

console.log(Object instanceof Function)//true
console.log(Object instanceof Object)//true
console.log(Function instanceof Funtion)//true  let fun = new Function()
console.log(Function instanceof Object)//true
function Fun(){}
console.log(Object instanceof Foo) //false
原型面试题
var A = function(){

}
a.prototype.n = 1
var b = new A() 
A.prototype = {
    n:2
    m:3
}
var c = new A()
conssole.log(b.n,b.m,c.n,c.m) //1 ,undefined,2,3
var F = function(){}

Object.prototype.b = function(){
    console.log('a()')
}

Function.prototype.b = function(){
    console.log('a()')
}
var f = new F()
f.a()
f.b() //b unedfined
F.a()
F.b()
执行上下文与执行上下文栈
 变量声名提升,在定义语句之前可以访问到
     值:undefined
 函数声明提升:(不是很细节)
 通过function声明的函数,在之前可以调用
     值:函数定义(对象)
 字面量定义的函数,不存在函数声明提升。
console.log(a1,window.a1)
window.a2();
console.log(this)

var  a1 = 3
function a2(){}
函数执行上下文:
    在调用函数,准备执行函数体之前,创建对相应函数执行上下文对象
    对局部数据进行处理
    
    形参变量==>赋值(实参)==>添加执行上下文属性
    arguments==>赋值(实参列表),添加为执行上下文属性
    var 定义的局部变量==>undefined,添加为执行上下文属性
    function  声明的函数 ==>赋值(fun),添加为执行上下文的方法
    this==>赋值(调用函数的对象)
    开始执行代码
function fn (a1){
    console.log(a1)//2
    console.log(a2)//undefined
    a3() //a()
    console.log(this) //window
    console.log(arguments) //伪数组
    var a = 3
    function a3(){
        console.log('a3()')
    }
}
   fn(a,3)

函数的执行上下文是在自己的作用域内开辟的一块(栈)空间

执行上下文栈
                        //1.进入全局上下文
var a = 10
var bar = function(x){
    var b = 5
    foo( x + b )        //3、进入foo执行上下文
}
var foo = function(y){
    var c = 5
    console.log(a+c+y)
}
bar(8)                   //2、进入bar函数上下文

函数执行完毕就会释放当前的内存空间,(出栈)

最终保留的就是window的执行


执行上下文题目:
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)

//结果输出:1,2,3,3,2,1, 1
//递归调用的,未完当前函数操作继续执行该函数,当递归条件不支持时,就会执行出栈操作
//整个过程产生 5 个执行上下文 (funtion) 
var c =1
function c(c){
      console.log(c)
}
c(2) //报错  =>var c = 1存在变量提升访问cc是一个变量
function a(){}
var a
console.log(typeof a)//'undefined'
//先执行变量提升,在执行函数提升
//实际代码的执行顺序
var a
function a(){}
执行上下文和代码的执行是俩快区域,当在执行代码块访问变量时,
先去执行上下文查看是,第一个名为 a的是一个 var a所以执行返回的是 'undefined'

if(!(b in window)){   //b in window => window中存在 b这个属性嘛?
        var b = 1
}
console.log(b)  //undefined

参考文章: