js中 for of、for in、 call 、apply、bind记录

for of 和 for in

  1. for of遍历值,for in遍历下标
  2. for in遍历出来的下标类型是string
  3. for in可以根据原型链遍历实例对象的属性名
  4. for of不能遍历对象。因为能够被for of正常遍历的数据类型都需要实现一个遍历器Iterator。而数组、字符串、Set、Map结构,早就内置好了Iterator(迭代器),它们的原型中都有一个Symbol.iterator方法,而Object对象并没有实现这个接口,使得它无法被for of遍历。可以在Object原型上声明Symbol.interator方法,代码在下面
//对数组
let arr = ['a','b','c']
for(let index in arr){
  console.log(index, typeof index)
}
//0 string
//1 string
//2 string

for(let value of arr){
  console.log(value)
}
//1  2  3

let arr = ["a", "b", "c"];
arr.name = "arr";
arr.getName = function () {
  return this.name;
};
//实例对象的隐式原型=构造函数的显式原型
arr.__proto__.constructor.prototype.sayHello = function () {
  return "hello";
};
arr.__proto__.constructor.prototype.parentName = "say uncle";
for (let i in arr) {
  if (arr.hasOwnProperty(i)) {
    console.log("ownProperty", i);
    // '0', '1', '2', 'name', 'getName'
  } else {
    console.log("not ownProperty", i);
    // 'sayHello', 'parentName'
  }
}
//hasOwnProperty():判断对象自身是否有这个属性


//给Object添加迭代函数
Object.prototype[Symbol.iterator] = function () {
  let _this = this;//this是进行迭代循环的obj
  let index = 0;//用来判断是否结束迭代的依据
  let length = Object.keys(_this).length;
  return {
    //done为true时结束迭代,done为false时再调用next方法
    next: () => {
      let value = _this[Object.keys(_this)[index]];//Object.keys获取对象的键值再放到数组里面
      let done = index >= length;
      index++;
      return { value, done };
    },
  };
};
//Object的其他两个方法
Object.defineProperty(obj,props)//根据props中提供的键值对,定义或修改obj中的键值对,返回的是修改后的obj,不是一个新对象
Object.getOwnPropertyDescriptors(obj)//获取obj的可描述性属性。
//返回格式:{key:{value: , configurable: false, enumerable: false, get: ƒ (), set: ƒ (data)}}
//configurable决定了能否删除改属性,enumerable决定该属性能否枚举

call apply bind

  1. 调用形式: func.call(newThis, args1, args2...) ; func.apply(newThis, [args1, args2...]) ; func.bind(newThis)(args1, args2...)
  2. 返回值: func.call和func.apply返回值就是函数func的返回值,func.bind(newThis)返回值是一个新函数
  3. 手写实现
	实现apply()
	Function.prototype.MyApply = function(context, argsArr){
	  //判断调用MyApply的是否是一个函数
	  if (!(typeof this === "function")) {
	    throw new TypeError(`${this} is not a function`);
	  }
	  //传递的参数不是数组的情况下 报错
	  if (!Array.isArray(argsArr)) {
	    throw new TypeError("CreateListFromArrayLike called on non-object");
	  }
	  //其他情况下 开始包装新的上下文
	  context = Object(context || window);
	  
	  //要改变新的this  就要用context调用this方法 所以要把this方法放到context的属性上让context调用
	  const symbolFunc = Symbol(); //不可重复的变量
	  context.symbolFunc = this;
	  const result = context.symbolFunc(...argsArr);
	  delete context.symbolFunc;
	  return result;
	};
	实现call()
	Function.prototype.MyCall = function(context, ...args){
	  //判断调用MyApply的是否是一个函数
	  if (!(typeof this === "function")) {
	    throw new TypeError(`${this} is not a function`);
	  }
	  //其他情况下 开始包装新的上下文
	  context = Object(context || window);
	
	  //要改变新的this  就要用context调用this方法 所以要把this方法放到context的属性上让context调用
	  const symbolFunc = Symbol(); //不可重复的变量
	  context.symbolFunc = this;
	  const result = context.symbolFunc(...args);//因为函数默认参数args会把args包装成数组,所以当调用MyCall传参时,如果传数组那么此时args就是[[args1,args2...]],如果传的是参数列表,那此时args就是[args1,args2...]
	  delete context.symbolFunc;
	  return result;
	};
	实现bind()
	Function.prototype.MyBind = function(context){
	  if (!(typeof this === "function")) {
	    throw new TypeError(`${this} is not a function`);
	  }
	  context = Object(context || window);
	  const symbolFunc = Symbol();
	  context.symbolFunc = this;
	
	  return function(...args){
	    const result = context.symbolFunc(...args);
	    delete context.symbolFunc;
	    return result;
	  }
	};
	
	//注意在调用bind生成新函数时,如果传了其他参数,那么调用bind生成函数时传的参数会被放到后面
	
	window.a = 'global'
	let obj = {
	  a:'obj'
	}
	function conA(...args){
	  console.log(this.a)
	  console.log(args) //['argu1','argu2','argu3']
	}
	let newCon = conA.bind(obj,'argu1')
	newCon('argu2','argu3')
  1. 补充
  • Object(arg)

    // 如果给定值是 null 或 undefined,将会创建并返回一个空对象
    console.log(Object(null)) //{...}
    // 如果传进去的是一个基本类型的值,则会构造其包装类型的对象
    console.log(Object(123)) //123 控制台打印的是123 但本质上是Number(123)
    console.log(typeof Object(123)) //object
    // 如果传进去的是引用类型的值,仍然会返回这个值,这是一个浅拷贝
    
    
  • delete xxx

    //用来删除对象的某属性,如果删除一个不存在的属性会没有效果但是也返回true
    //删除let var const声明的变量无效,并且返回false
    
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值