1.运算符与隐式类型转换

类型判断:

typeof constructor.toString().indexOf()
NaN是number
Array、Date、Null都是Object
function是function 未定义变量都是undefined
"John".constructor // 返回函数 String()
(3.14).constructor// 返回函数 Number() 
false.constructor// 返回函数 Boolean()
[1,2,3,4].constructor// 返回函数Array()
{name:'John', age:34}.constructor  // 返回函数 Object() 
new Date().constructor// 返回函数 Date()
function () {}.constructor// 返回函数 Function()

类型转换:

  • 对象转基本类型:

    先调用valueOf()再调用toString()
  • 其他简单类型-->String:
方法 注意
变量+""
String(变量)
变量.toString() ull和undefined这两个值没有toString()方法,
Number.toString(2);将数字转成二进制
ArrayObject.toString()会转为逗号分隔的列表内容
  • 其他数据类型-->Number:
方法 注意
Number(变量) true-->1 ; false-->0 ; null-->0 ;""或空格串-->0;
undefined-->NaN;非纯数字串-->NaN;
parseInt(变量,进制) 只保留开头数字,小数自动截断,非字符串会先自动转字符串。
两个参数时做进制转换
parseFloat(变量) 可以获得有效的小数部分
  • 转换为Boolean:

    0、-0、NaN、空串、null、undefined会转成false,其他都转成true
  • 伪数组转数组:

    Array.prototype.slice.call(arguments)

隐式类型转换:

算术运算符
- * / +
自动转换为Number

任何值和NaN计算结果都是NaN

任何的值和字符串做加法运算都会先转换为字符串,然后再做拼串操作
如[1,2]+[2,3]="1,22,3" 'a'+ +'b'="aNaN"
一元运算符
typeof + - ++ --
对一个其他的数据类型使用+ - ++ -- 会将其转换为数字
逻辑运算符

&& || !
能参与逻辑运算的都是布尔值

非布尔值会先转换成布尔值
关系运算符

&& || !
*比较:非数值比较会先转换成数字
&nbsp&nbsp&nbsp&nbsp两个字符串比较不会转换,而是比较它们的unicode编码

&nbsp&nbsp&nbsp&nbsp任何值与NaN作比较都是false。(只有NaN自己不等于自己)

*判等:==不同类型会转为相同类型(大部分时候转为数字)

&nbsp&nbsp&nbsp&nbsp===不会做类型转换

调用非函数,或者读取null或者undefined的属性时,会报错 :

isNaN("foo"); // true
isNaN(undefined); // true
isNaN({}); // true

2.创建对象的方法

  1. new Object();
  2. 工厂函数(一个返回Object的函数)
  3. 构造函数,必须使用new来调用,this指向新建的对象。

    new 一个构造函数的执行流程

    (1)开辟内存空间,存储新创建的对象

    (2)链接到原型,

    (3)绑定this到新建对象,执行构造函数

    (4)将新建的对象作为返回值返回

通过同一个构造函数实例化的多个对象具有相同的原型对象。

实例对象有一个__proto__属性,指向该实例对象对应的原型对象

实例.__proto__.constructor==构造函数 //true

构造函数有prototype属性,实例有__proto__属性

实例.__proto__==构造函数.prototype

试着实现一下instanceof:

function instanceof(left, right) {
// 获得类型的原型
let prototype = right.prototype
// 获得对象的原型
left = left.__proto__
// 判断对象的类型是否等于类型的原型
while (true) {
if (left === null)
return false
if (prototype === left)
return true
left = left.__proto__
}
}

3.闭包

闭包是指有权访问另一函数作用域中的变量的函数。

换句话说,在函数内定义一个嵌套的函数时,就构成了一个闭包, 它允许嵌套函数访问外层函数的变量。 通过返回嵌套函数,允许你维护对外部函数中局部变量、参数、和内函数声明的访问。

这种封装允许你在外部作用域中隐藏和保护执行环境,并且暴露公共接口,进而通过公共接口执行进一步的操作。

缺点:函数执行完后, 函数内的局部变量没有释放,占用内存时间会变长,容易造成内存泄露。

解决:能不用闭包就不用,及时释放。(将引用置为null)

经典面试题:

循环中使用闭包解决 var 定义函数的问题:

  • 解决方法一,使用闭包:

    (包装了一层立即执行函数,这样就不会污染全局变量了)

  • 解决方法二,使用let:

  • 解决方法三,使用setTimeout的第三个参数:

4.作用域和上下文

作用域(Scope)和上下文(Context)

作用域决定了代码区块中变量和其他资源的可见性。它指一个变量的作用范围。相对于上下文对象是静态的, 在编写代码时就确定了。

上下文(context)是指 this 在同一作用域内的值,是代码的执行环境。

执行上下文是动态的, 调用函数时创建, 函数调用结束时就会自动释放。

有三种类型的ECMAScript代码:全局代码,函数代码和eval代码。代码执行在它的执行上下文里。有唯一的全局上下文,以及可能有多个函数和eval上下文。

1.在全局代码执行前, JS引擎就会创建一个栈来存储管理所有的执行上下文对象

2.在全局执行上下文(window)确定后, 将其添加到栈中(压栈)

3.在函数执行上下文创建后, 将其添加到栈中(压栈)

4.在当前函数执行完后,将栈顶的对象移除(出栈)

5.当所有的代码执行完后, 栈中只剩下window

5.内存溢出和内存泄漏

内存溢出:一种程序运行出现的错误。当程序运行需要的内存超过了剩余的内存时, 就出抛出内存溢出的错误。

内存泄漏:占用的内存没有及时释放。

注意,内存泄露的次数积累多了,就容易导致内存溢出。

常见的内存泄露:

•意外的全局变量

•没有及时清理的计时器或回调函数

6.深浅拷贝

将引用复制改为值复制:

  • Object.assign(target, ...sources)

    将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。 不会跳过那些值为 null 或 undefined 的源对象。

    只能解决第一层的问题
  • 展开运算符 let b = {...a}

    只能解决一层
  • JSON.parse(JSON.stringify(object))

    会忽略 undefined、symbol

    不能序列化函数

    不能解决循环引用(父子循环引用、兄弟循环引用)的对象
/**
* 对象克隆
* 支持基本数据类型及对象
* 递归方法
*/
// 方法一:
function clone(obj) {
var o;
switch (typeof obj) {
case "undefined":
break;
case "string":
o = obj + "";
break;
case "number":
o = obj - 0;
break;
case "boolean":
o = obj;
break;
case "object": // object 分为两种情况 对象(Object)或数组(Array)
if (obj === null) {
o = null;
} else {
if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
o = [];
for (var i = 0; i < obj.length; i++) {
o.push(clone(obj[i]));
}
} else {
o = {};
for (var k in obj) {
o[k] = clone(obj[k]);
}
}
}
break;
default:
o = obj;
break;
}
return o;
}

7.异步与同步

  js 是单线程,而且有一个任务队列:全部的同步任务执行完毕后,再来执行异步任务。

  同步任务在主线程上排队执行,异步任务在任务队列等待,主线程上的同步任务执行完了,才会从任务队列取出异步任务执行。

常见的异步操作:网络请求、定时任务、事件绑定、promise

异步编程的4种方式:
  • 回调函数
  • 事件监听
f1.on('done', f2);
f1.trigger('done');
  • 发布/订阅
jQuery.subscribe("done", f2);
jQuery.publish("done");
jQuery.unsubscribe("done", f2);
  • promise对象

8.伪数组

特性:具有length属性、按索引方式存储数据、不具有数组的push,pop等方法。

例子:函数的arguments参数,调用getElementsByTagName,document.childNodes之类的返回的NodeList对象。

将伪数组转为数组:

function log(){
var args = Array.prototype.slice.call(arguments);
//为了使用unshift数组方法,将argument转化为真正的数组
args.unshift('(app)');
console.log.apply(console, args);
};

9.arguments的callee和caller属性

两个属性都是指针

arguments.callee指向当前函数,

arguments.caller指向当前函数的父函数

可用于递归函数中的自调用,实现函数执行与函数名的解耦合。

10.this、call、apply、bind

this 表示当前对象的一个引用

• 在方法中,this 表示该方法所属的对象。

• 如果单独使用,this 表示全局对象。

• 在函数中,this 表示全局对象。

• 在函数中,在严格模式下,this 是未定义的(undefined)。

• 在事件中,this 表示接收事件的元素。

类似 call() 和 apply() 方法可以将 this 引用到任何对象。

call、apply是立即调用函数,apply的第二个参数是参数数组。

persion1.say.call(p2, "实验小学", "六年级");
persion1.say.apply(p2, ["实验小学", "六年级"]);

将第一个参数p2作为say方法内this的指向,后面的参数作为say函数的参数。

bind传参与call相同,但bind返回一个函数,要加()才能立即执行。

persion1.say.bind(p2, "实验小学", "六年级")();

11.事件机制

事件触发的三个阶段 :

  路径:Window <——> Document <——> <html> <——> … <——> 事件触发处

  • 捕获阶段:遇到注册的捕获事件会触发
  • 目标阶段:传播到事件触发处时触发注册的事件
  • 冒泡阶段:遇到注册的冒泡事件会触发

    如果给一个目标节点同时注册冒泡和捕获事件,事件触发会按照注册的顺序执行。

注册事件:

  属性注册:

  

  • <button onlick="sayHello()">点击</button>

  方法注册:

  • element.addEventListener(event, function, useCapture);

        //usecapture默认false冒泡,true捕获
  • element.attachEvent(event,function); //IE中
  • EventTarget.onEventName=function(e){};

注销事件:

  • removeEventListener(event,function,capture/bubble); 
  • detachEvent(event,function); 
  • 事件属性赋值为null

阻止事件冒泡:

box3.onclick = function (event) {
alert("child");
//阻止冒泡
event = event || window.event;
if (event && event.stopPropagation) {
event.stopPropagation();//w3c(火狐、谷歌、IE11)
} else {
event.cancelBubble = true;//IE10以下
}
}

事件委托(事件代理):

如果一个节点中的子节点是动态生成的,那么子节点需要注册事件的话应该委托给父节点

优点:减少内存消耗,提高性能。

12.BOM与DOM

BOM与DOM的关系:

系统对话框:

alert();	//不同浏览器中的外观是不一样的
confirm(); //兼容不好
prompt(); //不推荐使用

window操作窗口

  window.open(url,target,param)

  window.close()

  新窗口.moveTo(5,5)

  新窗口.resizeTo()

  window.resizeBy()

location对象:

window.location可以简写成location。location相当于浏览器地址栏,可以将url解析成独立的片段。

  • 属性

    • href:跳转
    • hash 返回url中#后面的内容,包含#
    • host 主机名,包括端口
    • hostname 主机名
    • pathname url中的路径部分
    • protocol 协议 一般是http、https
    • search 查询字符串
  • 方法
    • location.assign():改变浏览器地址栏的地址,并记录到历史中

      设置location.href 就会调用assign()。一般使用location.href 进行页面之间的跳转。
    • location.replace():替换浏览器地址栏的地址,不会记录到历史中
    • location.reload():重新加载

navigator对象:

window.navigator的一些属性 可以获取客户端的一些信息。

appCodeName appName appVersion cookieEnabled platform userAgent systemLanguage

history对象:

window.history 包含用户(在浏览器窗口中)访问过的 URL。

方法 描述
back() 加载 history 列表中的前一个 URL
forward() 加载 history 列表中的下一个 URL
go() 加载 history 列表中的某个具体页面

screen对象:

Screen 对象包含有关客户端显示屏幕的信息。

availHeight availWidth colorDepth height width pixelDepth

【前端必备】三、JS篇的更多相关文章

  1. 前端必备的js知识点(转载)

    1.本文主体源自:http://www.cnblogs.com/coco1s/p/4029708.html,有兴趣的可以直接去那里看,也可以看看我整理加拓展的.2.js是一门什么样的语言及特点?    ...

  2. 前端面试(原生js篇) - DOM

    根据我的面试经历,一般小公司的面试环节,比较关心框架的熟练程度,以及独立开发组件的能力 但大厂通常有五轮以上的面试,而且对 js 基础语法很是看重 于是我总结了一些关于 js 基础的面试对话,有的当时 ...

  3. 前端深入之js篇丨Array数组操作从入门到成神Up Up Up,持续更新中

    写在前面 随着前端深入的不断学习,发现数组这个数据结构在前端中有着相当大的存在感,由于我初学前端的时候并没有系统性的学习数组,所以我将通过这篇文章同你一起学习数组,希望我们能一起进步,学会熟练操作数组 ...

  4. 前端面试(原生js篇) - 精确运算

    一.面试题 问:开发的时候有用到过 Math 吗? 答:很多啊.比如生成 GUID 的时候,就会用到 Math.random() 来生成随机数. 问:别的呢?比如向下取整.向上取整? 答:向下取整是  ...

  5. 前端自动化(三) 合并压缩css、压缩js、添加时间戳、打包上线操作

    前端自动化(三)   合并压缩css.压缩js.添加时间戳.打包上线操作 此文在前两篇基础上对比参考,会很方便理解 gulp.task("delete",function(){ r ...

  6. 前端第三篇---前端基础之JavaScript

    前端第三篇---前端基础之JavaScript 一.JavaScript概述 二.JavaScript的基础 三.词法分析 四.JavaScript的内置对象和方法 五.BOM对象 六.DOM对象 七 ...

  7. 前端开发者使用JS框架的三个等级

    目前前端开发者使用JS框架是种很普遍的现象,因为框架可以加快开发速度,同时避免各类浏览器的兼容性问题.不过同样是用框架开发,不同开发者的境界水平还是有一定差距,本文将这些前端开发者分为三个等级. 第一 ...

  8. 月薪12k的零基础自学前端必备手册

    随着互联网的深入发展,前端开发工程师一跃成为市场上非常抢手的人才.很多同学,包括以前做UI的.Java的.或者对于IT完全零基础的同学都想学习前端.下图是网上流传甚广的一张前端学习思维导图,很多初学者 ...

  9. 好程序员分享Web前端面试题汇总JS篇之跨域问题

    为什么80%的码农都做不了架构师?>>>   好程序员分享Web前端面试题汇总JS篇之跨域问题,接着上一篇文章我们继续来探讨web前端面试必备面试题. 跨域解决方案 1. 通过jso ...

  10. webpack入门--前端必备

    webpack入门--前端必备 什么是 webpack? webpack是一款模块加载器兼打包工具,它能把各种资源,例如JS(含JSX).coffee.样式(含less/sass).图片等都作为模块来 ...

随机推荐

  1. 图论:Prufer编码-Cayley定理

    BZOJ1430:运用Cayley定理解决树的形态统计问题 由Prufer编码可以引申出来一个定理:Cayley 内容是不同的n结点标号的树的数量为n^(n-2) 换一种说法就是一棵无根树,当知道结点 ...

  2. Parallel

    介绍 C# 4.0 的新特性之并行运算 Parallel.For - for 循环的并行运算 Parallel.ForEach - foreach 循环的并行运算 Parallel.Invoke - ...

  3. Tomcat报错:Failed to start component [StandardEngine[Catalina].StandardHost[localhost].StandardContext[/JFreeChartTest]]

    最好把项目移除,然后在tomcat的webapps发布路径下也把项目文件删掉,重新部署就好了,原因是可能在tomcat的remove覆盖中以前的文件有所保留导致冲突,亲测有效

  4. 关于ssh三大框架整合的碎碎念

    三大框架整合,无非就是一个导jar包,修改配置文件的过程.完了就没事了. 还是有很多细节性的问题 比如在spring中写applicationContext.xml文件时不提示: 解决方法如下: 如果 ...

  5. C语言分割字符串函数strtok

    在编程过程中,有时需要对字符串进行分割.而有效使用这些字符串分隔函数将会给我们带来很多的便利. 下面我将在MSDN中学到的strtok函数做如下翻译. strtok :在一个字符串查找下一个符号 ch ...

  6. 【DLL】动态库的创建,隐式加载和显式加载(转)

    原文转自:https://blog.csdn.net/dcrmg/article/details/53437913

  7. linux编程之信号

    信号(signal)机制是UNIX系统中最为古老的进程之间的通信机制,它用在一个或多个进程之间传递异步信号,信号可以由各种异步事件产生,如: 键盘中断等等,在Linux 的shell 中,也可以使用信 ...

  8. java===java基础学习(10)---对象构造

    重载 如果多个方法有相同的名字,不同的参数,便产生了重载.编译器必须挑选出具体执行哪个方法,他通过用各个方法给出的参数类I型那个与特定方法调用所使用的值类型进行匹配来挑选出相应的方法.如果编译器找不到 ...

  9. python基础===isinstance() 函数,判断一个对象是否是一个已知的类型

    isinstance(object, classinfo) object -- 实例对象. classinfo -- 可以是直接或间接类名.基本类型或者有它们组成的元组. >>>a ...

  10. nfs 文件共享 服务

    需要rpc服务: [root@xujiaxuan ftp]# service rpcbind start[root@xujiaxuan ftp]# chkconfig rpcbind on 设置开机自 ...