调用函数时this的指向和克隆

183 阅读2分钟

this

总结

    1. 作为构造函数时,this指向实例化对象
    2. 直接调用
            非严格模式下this指向globalThis 、严格模式下this指向undefined
    3. 哪个引用值调用它,this就指向该引用值
    4. 可以通过 apply | call | bind 来修改调用函数时的this指向

案例

// example1
var name = '222'
var a = {
  name: '111',
  say: function() {
    console.log(this.name)
  }
}

var fun = a.say
fun() // 直接调用this指向globalThis. 浏览器下:222,node下:undefined
a.say() // 引用值调用,this指向a:111 

var b = {
  name: '333',
  say: function(fun) {
    fun()
  }
}

b.say(a.say) // 直接调用this指向globalThis. 浏览器下:222,node下:undefined
b.say = a.say
b.say() // 引用值调用,this指向b:333


// example2
var foo = 123
function print() {
    this.foo = 234 // 实例对象添加foo属性并赋值
    console.log(foo)// 在该函数的AO对象上找不到,往上继续在GO中找到为foo:123
}
new print()



// *example3
/*
	GO:{
		a: undefined -> 5,
		go: function go(){}
	}
	go-AO:{
		a: undefined,
		test: function(){}
	}
	test-AO: {
		a: undefined -> 0,
	}
	 0 undefined 0 undefined
*/
var a = 5
function go() {
  var a
  function test() {
    a = 0 // 执行此语句时,沿着作用域链往上找变量a,然后赋值
    console.log(a) 
    console.log(this.a)
    /*
    	如果注释掉var a,则结果为 0 undefined 0 0
    		GO:{
                a: undefined -> 5,
                go: function go(){}
            }
            go-AO:{
                a: undefined -> 0,
                test: function(){}
            }
            test-AO: {}
    */
    var a 
    console.log(a)
  }
  test()
  console.log(a)
}
new go()

克隆

浅克隆


// 浅克隆:将Origin克隆到Target,引用值指向同一个地址
function shallowClone(Target,Origin) {
  var toStr = Object.prototype.toString
  Target = (typeof(Target) === 'object') ? Target : (toStr.call(Origin) === '[object Object]' ? {} : [])

  // 1. 遍历需要克隆的引用值所有属性,通过key-value将其克隆到别的引用值
  for (var prop in Origin) {
    Target[prop] = Origin[prop]
  }

  return Target
}

var arr1 = [1,2,3,{name:"arr1",ok:{age:18}}]
var arr2 = []
shallowClone(arr2,arr1)
arr2[0] = '1'
arr2[3].name = 'arr2'
arr2[3].ok = 'ok'
console.log('shalloClone:',arr1,arr2)

深克隆


// 深克隆:将Origin克隆到Target,并且互不影响
function deepClone(Target,Origin) {
  var toStr = Object.prototype.toString
  Target = (typeof(Target) === 'object') ? Target : (toStr.call(Origin) === '[object Object]' ? {} : [])

  // 1. 遍历引用值得属性
  for (var prop in Origin) {
    var ele = Origin[prop]

    // 2. 区分元素为(原始值 + null + undefined + NaN)还是(array + object)
    if (ele && typeof(ele) === 'object') {

      // 3. 区分 array object
      if (toStr.call(ele) === '[object Object]') {
        Target[prop] = {}
      } else {
        Target[prop] = []
      } 
      deepClone(Target[prop],ele)

    } else {
      Target[prop] = ele
    }
  }

  return Target
}


var arr1 = [1,2,3,{name:"arr1",ok:{age:18}}]
var arr2 = []
deepClone(arr2,arr1)
arr2[0] = '1'
arr2[3].name = 'arr2'
arr2[3].ok = 'ok'
console.log('deepClone:',arr1,arr2)