JS进阶2(数组 函数)

对象的属性数据属性访问器属性
数据属性:[[Configurable]][[Enumerable]][[Writable]][[Value]]前三个默认都是true,value默认undefined
要修改默认属性的值的话,使用Object.defineProperty(person(object name),“name”(属性),{writable:false});
访问器属性:[[Configurable]][[Enumerable]][[get]][[set]]
读取属性的特性:Object.getOwnPropertyDescriptor()

JS有哪些内置函数

Object,Array,Boolean,Number,String,Function,Data,RegExp,Error

判断属性是自有属性还是原型属性

自有属性: obj.hasOwnProperty()
原型属性:属性in obj&&!obj.hasOwnProperty()
isPrototypeOf()

JS中什么是类(伪)数组,如何将类数组转化为标准数组

1.argument参数
2.getElementByTagName
3.document.childNodes返回的都是伪数组
可以通过Array.prototype.slice.call(fakeArray)转换(将对象转化为数组)

检测数组

1.Array.isArray(value)//检测是否为数组
2.value instanceof Array
3. arr.constructor === Array
4. Object.prototype.toString.call(arr) === ‘[object Array]’

Array类型

3.栈方法,push(),pop()
4.队列方法,push()末端添加,pop()弹出最后,shift()移除第一个,unshift()从前面插入
5.重排序方法value.sort(),reverse()
6.操作方法concat()()合并数组(不是改变自身数组,而是创建新数组)
7.位置方法indexOf()(返回下标),lastIndexOf()(返回最后一个下标)

迭代方法

every()运行该函数的作用域对象,如果每一项返回TRUE,则返回true,
filter()返回满足条件的项组成的数组,
forEach()对数组中的每一项运行函数,这个方法无返回值,
map()返回运行结果组成的数组,
some()任意一项满足条件,则返回TRUE
9.归并方法reduce(),reduceRight()

对象的toString(),toLocaleString(),valueof()

toString()返回以逗号拼接的字符串
valueOf()返回的还是数组

slice(),splice()

1.slice :创建一个新数组不会修改原来数组的值。
用法:slice( para1 ),会截取从para1开始的到原数组最后的部分;
slice(para1,para2)会截取原数组的从para1开始的para2-para1的数组(不包括para2)。
2. splice :改变原数组
用法 : splice( para1,para2 ) : 删除数组中任意数量的项,从para1开始的para2项。会导致数组length值的改变
splice( para1,para2,val1,val2… )插入(起始位置,0,要插入的项)
splice( para1,para2,val1,val2… ):替换(起始位置,要删除的项数,要插入的项)
3.split : 根据特定的字符切割字符串并且返回生成的数组。

join()和split()区别

(1)split()用于分割字符串,返回一个数组,例如
var string=“hello world?name=xiaobai”;
var splitString = string.split("?");
console.log(splitString);//[“hello world”,“name=xiaobai”]
split()只有一个参数时:分割的字符串或正则表达式;两个参数时,第二个参数是指返回的数组中元素的个数;
(2)join()用于连接多个字符或字符串,返回值为一个字符串;
例如 : str = “s-aaa-sss-eee-www”;
targetArr = str.split(“-”); //[‘s’,’aaa’,’sss’,’eee’,’www’]

    a[0]="XHTML";
    a[1]="CSS";
    a[2]="JavaScript";
    alert(a.join("#")); //XHTML#css#JavaScript

定义函数的方法

函数声明function hello(){}
函数表达式。var a=function (){//…};//匿名函数,name属性为空
解析器会先读取函数声明,而函数表达式必须等到解析器执行到他所在的代码行,才会被执行。
1.参数都保存在arguments数组里。
2.参数都是值,不可能通过引用传递参数。
3.没有重载,如果定义了两个同名函数,后者覆盖前者。(把函数名想像成指针)
4.一个函数可能有多个名字
5.函数可以作为返回值使用,可以将一个函数作为另一个函数的结果返回。
5.return后面的语句永远不会执行
6.函数的调用方式:直接调用,作为对象方法调用,作为构造函数调用,通过call和apply方法调用

关于this对象

函数里的this可以分为两种来记忆:
1.如果是使用new方式创建对象,this指向新建的那个对象;
2.如果只是普通的调用,谁调用这个函数,函数里的this就指向谁~

3.匿名函数的this对象为window
4.this要在执行是确认值,定义时无法确认
1.隐式绑定: 看调用位置是否有上下文对象,即是否被某个对象拥有或包含(这里说的包含可不是用花括号包起来呦~)。
2.显示绑定:使用一些方法强制将函数绑定在某个对象上,这些方法就是 call(…) apply(…) 这两种方法的工作方式是类似的,所以我们就以call()来作为例子分析一下他们的工作过程
3.new 绑定: 创建一个全新的对象 这个对象会被执行[proto]的链接,这个新对象会绑定到函数调用的this上,如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象
4.默认绑定 默认绑定就是不符合上面任何一种规则是的默认规则.看执行时而非定义时,只要函数(function)没有绑定在对象上调用,它的 this 就是 window。

关于bind()、call() 和 apply()

三者的相似之处:
1、都是用来改变函数的this对象的指向的。
2、第一个参数都是this要指向的对象。
3、都可以利用后续参数传参。
不同:
call()在第一个参数之后的 后续所有参数就是传入该函数的值。
apply() 只有两个参数,第一个是对象,第二个是数组,这个数组就是该函数的参数。
call和apply都是对函数的直接调用,而bind方法 只有两个参数,第一个是对象,第二个是数组,返回的仍然是一个函数,因此后面还需要()来进行调用才可以。
如果你打算直接传入arguments对象,或者包含函数中先接收到的也是一个数组,那么使用apply()肯定更方便;否则,选择call()可能更合适。
bind()最简单的用法是创建一个函数,使这个函数不论怎么调用都有同样的this值

应用场景

1、合并两个数组

Array.prototype.push.apply(vegetables, moreVegs);// 4

2、调用父构造函数实现继承

function  SubType(){
    // 核心代码,继承自SuperType
    SuperType.call(this);
}

3.扩充函数作用域,使对象与方法解耦

使用apply实现bind

Function.prototype.bind = function(context){
  self = this;  //保存this,即调用bind方法的目标函数
  return function(){
      return self.apply(context,arguments);
  };
};

使用原生js实现call apply bind

if(!Function.prototype.bind){
  Function.prototype.bind = function(context){
    // 首先判断this是不是function
    if(typeof this !== 'function'){
      // 抛出错误
    }
    var _this = this,
          fNOP = function(){},    // 用于后面维护原型关系
          args = Array.prototype.slice.call(arguments, 1),    // 取出bind收到的参数,除去第一个作为上下文的参数并保存
          fBound = function(){
            _this.call(context, args.concat(Array.prototype.slice.call(arguments)))   // 将bind接收的的参数和实际接收到的参数相连接
          };
    // 维护原型关系
    if(this.prototype){
        fNOP.prototype = this.prototype;
        fBound.prototype = new fNOP;
    }
    return fBound;
  }
}

递归代码在数组偏大的情况下会导致堆栈溢出。

var list = readHugeList();
var nextListItem = function() {   
 var item = list.pop();    if (item) {        // process the list item...
        nextListItem();
    }
};
var list = readHugeList();
var nextListItem = function() {   
 var item = list.pop();    if (item) {        // process the list item...
        setTimeout( nextListItem, 0);
    }
};

事件循环操纵了递归,而不是调用堆栈。如果 item不为空,timeout函数(nextListItem)就会被推到事件队列,因此就清空调用堆栈。当事件队列运行其timeout事件,且进行到下一个 item 时,定时器被设置为再次调用 nextListItem。因此,该方法从头到尾都没有直接的递归调用,所以无论迭代次数的多少,调用堆栈保持清空的状态。

对象的扩展,密封,冻结

扩展特性
Object.isExtensible 方法
Object.preventExtensions 方法
密封对象是指那些不能添加新的属性,不能删除已有属性,以及不能修改已有属性的可枚举性,但可能可以修改已有属性的值的对象。
Object.isSealed 方法
Object.seal 方法
冻结特性是指它不可扩展,所有属性都是不可配置的,且所有数据属性都是不可写的。
Object.isFrozen 方法
Object.freeze 方法

遍历对象的方法

for in、Object.keys、Object.getOwnProperty

深复制

function deepCopy(obj) {
      var result = Array.isArray(obj) ? [] : {};
      for (var key in obj) {
        if (obj.hasOwnProperty(key)) {
          if (typeof obj[key] === 'object') {
            result[key] = deepCopy(obj[key]);   //递归复制
          } else {
            result[key] = obj[key];
          }
        }
      }
      return result;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值