js高级

372 阅读10分钟

js高级:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::: ////////////////////////////////////////

面相对象编程基本思路(模型)

  1. 在构造函数里面写实例的属性
  2. 在原型上写共享的数据

/////////////////////////////////////////////////////////////////

相等转换规则:(注意点:是往下匹配,一条一条的匹配,匹配到了就直接运用)

  1. NaN 与任何值不相等,包括他自己
  2. null 与任何值不相等,除了null和undefined
  3. undefined 与任何值不相等,除了null和undefined
  4. 如果操作数两边有数字或是布尔,都转成数字进行比较
  5. 如果操作数两边有字符串,都转成字符串进行比较
  6. 如果操作数两边都是复杂数据类型,那就比较地址

//////////////////////////////////////////////////////////////////

逻辑中断: && :从左到右 找假值 (布尔类型为false),如果找到了,逻辑就中断,返回假值 不是返回true或者false 返回的是布尔类型为false的那个值本身

=== 全等 比较的是类型和值 == 相等 相等在比较的时候会隐式转换成 同一种类型 进行比较

/////////////////////////////////// function Person(){

} var p = new Person();

console.log(p.proto === Person.prototype); // true 实例的__proto__和构造函数的prototype指向的是同一个东西(原型)

/////////////////////////////////

console.log(p.constructor == Person); // true console.log(p.constructor == Person.prototype.constructor); // true

///////////////////////////////////////

设置原则:

  1. 如果对象没有该属性,就添加该属性,值为赋值的值。
  2. 如果对象有该属性,就覆盖原来的值

小结: 属性搜索原则: 沿着原型链查找 属性设置原则: 有,就覆盖,没有,就添加

///////////////////////////////////

hasOwnProperty() 语法: 对象.hasOwnProperty("属性"); 作用: 判断该属性是否是对象自身的,如果是返回true,不是就返回false,在原型上的不算

in 运算符: 判断属性能否被对象访问到,不管属性是对象自身的,还是原型链上的,只要能够访问到, 就返回true,如果访问不到就返回false

propertyIsEnumerable(): 语法: 对象.propertyIsEnumerable("属性") 作用: 判断属性是否可遍历 1. 判断属性是否是对象自身的 2. 判断属性是否可遍历 只有满足了上面两个条件才返回true

对象A.isPrototypeOf(对象B);对象A是否是B的原型

///////////////////////////////////////////////

什么是闭包? 闭包是一个能够读取其他函数内部变量的函数 闭包可以简单理解成 定义在函数内部的函数 从本质上来讲,闭包是将函数内部和函数外部连接起来的桥梁;

能够对私有变量进行操作 如果一个函数被其父函数以外的变量引用,就会形成闭包

闭包的3个特性: 1 函数嵌套函数 2 函数内部可以引用函数外部的参数和变量 3 参数和变量不会被垃圾回收机制回收

优点: 1 保护函数内的变量安全 2 在内存中维持一个变量 可以做缓存 3 匿名自执行函数可以减少内存消耗

缺点: 1 会造成内存泄漏 (解决方法:使用完变量之后手动为其赋值null) 2 由于闭包涉及跨域访问,会导致性能损失(解决方法:把跨作用域的变量存储在局部变量中,然后直接访问局部变量来减轻对执行速度的影响)

//////////////////////////////////////////////////////////////

valueOf(): 将对象转成原始值(简单数据类型),但是默认的(Object.prototype上的valueOf)只能返回对象自身 特殊的: 日期对象的valuOf()返回的是时间戳(因为日期的原型上有自己的valueOf方法)

toString(): 将对象转成字符串,每个内置对象的原型上都提供了toString方法 toLocaleString(): 和toString没差别,只在 日期对象上有区别

console.log(date.toString()); // Mon Sep 03 2018 18:18:58 GMT+0800 (中国标准时间) console.log(date.toLocaleString()); // 当地时间

小结: valueOf(): 转成简单数据类型,默认情况下返回对象自身 toString(): 转成字符串

对象在参与运算或者是比较的时候,js内部会帮我们自动调用 valueOf && toString这两个方法的。 调用规则:

  1. 首先调用valueOf方法,尝试将对象转成简单数据类型,如果没有转成简单数据类型,就继续调研toString方法,将对象转成字符串
  2. 如果对象分别调用valueOf和toString这两个方法,都没有转成简单数据类型,会报错

//////////////////////////////////////////////////////////////

由于咱们的自调用函数内部的代码不会影响到全局,和沙箱模式一样,所以我们也说自调用函数也是沙箱模式

沙箱模式:是一个独立和封装的环境,内部的代码是不会影响到外部的 自调用函数:创建了一个函数,同时调用了这个函数

/////////////////////////////////////////////////////////////////

继承: 混入式继承:拷贝一个对象的属性和方法 原型链继承:通过构造函数创建的实例对象可以直接继承原型上的任何成员 混入式+原型链继承: 经典继承:var 实例 = Object.create(obj);该方法创建并返回一个空对象,返回的对象的原型是参数obj (其实就是把一个对象添加大Object的create属性上了) console.log(实例.proto === obj) //true

///////////////////////////////////////////////

定义函数的三种方式: 1 函数声明---function fn(){...} 2 函数表达式--var fn = function(){...} 3 构造函数创建函数---var fn=new Function(参数1,参数..,函数体)---函数也是一个对象,new出来

///////////////////////////////////////////////////////

代码实时预览 :txt.addEventListener("keyup", function(){try(..)catch(e){..}} 对于可能会报错的代码,使用try()catch(){...},就会阻止报错

eval(): 将字符串视为js代码来执行

////////////////////////////////////

函数的四种调用模式: 1 函数调用模式 fn() this指向的是window 2 对象(方法)调用模式 obj.fn() 或者 obj"fn" this指向obj 3 构造函数调用模式 var p = new Person() this指向新创建的实例对象 4 上下文模式(借用模式) call 、apply (bind改变指向,但是不调用) call的参数有若干个,第一个参数是用来改变函数内的this指向的,其余的参数是作为调用函数的实参 当call的参数没有的时候,或者第一个参数为null,那么函数内的this指向为window

伪数组是个对象,有1数字下标和2length长度属性,能和数组一样遍历,但是3不能使用数组的方法

///////////////////////////////////////////////////

常见的伪数组有:

  1. arguments
  2. document.getElementsByTagName()
  3. jQuery对象 数组的push方法会添加项,还会自动去维护伪数组的length属性 join(): 数组的方法,用来拼接数组中的每一项的

伪数组是一个对象 伪数组转成真数组:obj = Array.prototype.slice.call(obj); 快速复制一份数组:var arr2 = arr.slice();

call 和 apply 的作用 一样,都有调用函数的作用 fn.apply(指向, 伪数组或者是数组); fn.call(指向, arg1, arg2, ....); apply的特性: apply的平铺性: 将数组的中每一项取出来,作为借用函数的实参

bind会1创建并返回一个新的函数, 新的函数和借用的函数是一模一样的, 但是2新函数内的this已经被固定了bind的参数 不论是何种调用模式,this都是指向这个bind的参数,3bind不会调用fn函数

///////////////////////////////////////////////////////////////////

setInterval(fn, 1000); 定时器 clearInterval()

///////////////////////////////////////////////////////////////

任何函数都是new Function 的实例, Function.prototype是函数的原型

slice(8, -1) // -1 : 从后面开始截取,截取几个,就看数字是几

所有函数即有prototype属性,也有__proto__ 属性

A instanceof B : A是否在B的原型链上

/////////////////////////////////////////////////////////////////

预解析: 预解析的规则:

  1. 优先提升函数,在是变量提升
  2. 如果遇到重名的变量声明, 会被忽略

建议:

  1. 不要重复的声明同一个变量,后面的声明被忽略
  2. 不要重复的声明同一个函数,后面的覆盖了前面的
  3. 不要让你的函数和变量重名(在同一个作用域内)

///////////////////////////////////////////////////////////////

在编程语言里面:

  1. 块级作用域: js不支持块级作用域 ,由花括号组成代码结构的范围 ({}),花括号里声明的变量外部是无法访问的
  2. 词法作用域 在js里面,只有函数才能形成作用域,所以词法作用域也叫函数作用域

自由变量: 对于一个函数来说,如果这个变量不是在这个函数内部声明的,但是却使用了这个变量,对于这个函数来说,这个变量就是自由变量

作用域链: 函数能够形成作用域,如果函数被嵌套在另一个函数中,嵌套的函数也有自己的作用域,从这个函数的作用域往外形成的一条链, 这个链叫做作用域链。

function fn(num1) { // var num1 = undefined } fn();//--> 函数里有形参的话,如果调用的时候没传参,就相当于 参数值=undefined;

///////////////////////////////////////////////////////////////////////////

递归函数: 内部自己调用了自己,一定要有结束条件不然就是死递归. 递归使用了划归思想,把一个复杂的问题转成简单的问题:将未知转成已知,一定要有结束条件

///////////////////////////////////////////////////////////////////////////

缓存:存储数据的容器(cache)使用数组或者是对象用来做存储数据的容器

使用缓存的思路:(兔子数量问题)

  1. 首先去缓存容器里面查看下有没有对应的数据
  2. 如果有,直接取出使用
  3. 如果没有,先去计算结果,把结果存储到缓存中,方便下次复用

闭包的形成条件: 有两个函数,是嵌套关系,内部函数还访问了外部函数的声明的变量。

函数在调用的时候,会在内存里面去开辟一块空间来执行函数内部的代码,当函数调用结束的时候,函数开辟的空间会被销毁掉。(正常) 闭包占用的内存是释放不了的。

闭包的作用:

  1. 私有变量,保护数据的安全
  2. 持久化维持数据

闭包的问题: 闭包占用的内存不会被释放的,造成内存泄漏的问题

内存泄漏:一块内存空间被占用了,一直得不到回收,别的对象就使用不了这块空间。 从引用计数、标记-清除算法来说,闭包占用的内存都是无法回收的。不要滥用闭包

手动释放闭包占用的内存: 闭包 = null;

引用计数算法:js会自动去分配内存,存储对象,0引用的对象,垃圾,被垃圾回收机制给回收掉--->定期检查是否有0引用的对象 例子:调用fn结束,理应要销毁fn中的对象,但是由于这些对象都不是0引用对象,就不能够被回收。多次调用这个fn函数,就会造成内存泄漏的问题。

标记-清除算法:从window上开始找,不能从window这个根对象上找不到的对象(垃圾),循环引用不是问题,现在都是用这个方法回收垃圾.遍历

///////////////////////////////////////////////////////////////////////////

正则表达式:

test(): 用来测试字符串是否符合正则的规律

  1. \d ==> 数字 0-9
  2. \D ==> 非数字
  3. \w ==> 字符 a-z 0-9 A-Z
  4. \W ==> 非字符
  5. \s ==> 空白字符
  6. \S ==> 非空白字符
  7. 点 (.)理解为任意字符