【前端】JavaScript 里的奇葩知识

【前端】JavaScript 里的奇葩知识
【前端】JavaScript 里的奇葩知识

Function.prototype竟然是个函数类型。而自定义函数的原型却是对象类型。

typeof Function.prototype === 'function'; // true

function People() {}

typeof People.prototype === 'object'; // true

所以我们设置空函数可以这么做:

// Good

const noop = Function.prototype;

// Bad

const noop = () => {};

一个变量真的会不等于自身吗?

const x = NaN;

x !== x // true

这是目前为止 js 语言中唯一的一个不等于自己的数据。为什么?因为NaN代表的是一个范围,而不是一个具体的

数值。在早期的isNaN()函数中,即使传入字符串,也会返回true,这个问题已经在 es6 中修复。

isNaN('abc'); // true

Number.isNaN('abc') // false

所以如果您想兼容旧浏览器,用x !== x来判断是不是NaN,是一个不错的方案。

构造函数如果return了新的数据

// 不返回

function People() {}

const people = new People(); // People {}

// 返回数字

function People() {

return1;

}

const people = new People(); // People {}

// 返回新对象

function Animal() {

return {

hello: 'world',

};

}

const animal = new Animal(); // { hello: 'world' }

在实例化构造函数时,返回非对象类型将不生效

.call.call到底在为谁疯狂打call?

function fn1() {

console.log(1);

}

function fn2() {

console.log(2);

}

fn1.call.call(fn2); // 2

所以fn1.call.call(fn2)等效于fn2.call(undefined)。而且无论您加多少个.call,效果也是一样的。

实例后的对象也能再次实例吗?

function People() {}

const lili = new People(); // People {}

const lucy = new tom.constructor(); // People {}

因为lili的原型链指向了People的原型,所以通过向上寻找特性,最终在Peopel.prototype上找到了构造器即People自身

setTimeout嵌套会发生什么奇怪的事情?

console.log(0, Date.now());

setTimeout(() => {

console.log(1, Date.now());

setTimeout(() => {

console.log(2, Date.now());

setTimeout(() => {

console.log(3, Date.now());

setTimeout(() => {

console.log(4, Date.now());

setTimeout(() => {

console.log(5, Date.now());

setTimeout(() => {

console.log(6, Date.now());

});

});

});

});

});

});

在0-4层,setTimeout的间隔是1ms,而到第 5 层时,间隔至少是4ms。

es6函数带默认参数时将生成声明作用域

var x = 10;

function fn(x = 2, y = function () { return x + 1 }) { var x = 5;

return y();

}

fn(); // 3

函数表达式(非函数声明)中的函数名不可覆盖

const c = function CC() {

CC = 123;

return CC;

};

c(); // Function

当然,如果设置var CC = 123,加声明关键词是可以覆盖的。

严格模式下,函数的this是undefined而不是Window

// 非严格

function fn1() {

return this;

}

fn1(); // Window

// 严格

function fn2() {

'use strict';

return this;

}

fn2(); // undefined

对于模块化的经过webpack打包的代码,基本都是严格模式的代码。

取整操作也可以用按位操作

var x = 1.23 | 0; // 1

因为按位操作只支持32位的整型,所以小数点部分全部都被抛弃

indexOf()不需要再比较数字

const arr = [1, 2, 3];

// 存在,等效于 > -1

if (~arr.indexOf(1)) {

}

// 不存在,等效于 === -1

!~arr.indexOf(1);

按位操作效率高点,代码也简洁一些。也可以使用es6的includes()。但写开源库需要考虑兼容性的道友还是用indexOf比较好

getter/setter也可以动态设置吗?

class Hello {

_name = 'lucy';

getName() {

return this._name;

}

// 静态的getter

get id() {

return1;

}

}

const hel = new Hello();

https://www.360docs.net/doc/8b10734879.html,; // undefined

hel.getName(); // lucy

// 动态的getter

Hello.prototype.__defineGetter__('name', function() { return this._name;

});

Hello.prototype.__defineSetter__('name', function(value) { this._name = value;

});

https://www.360docs.net/doc/8b10734879.html,; // lucy

hel.getName(); // lucy

https://www.360docs.net/doc/8b10734879.html, = 'jimi';

https://www.360docs.net/doc/8b10734879.html,; // jimi

hel.getName(); // jimi

0.3 - 0.2 !== 0.1// true

浮点操作不精确,老生常谈了,不过可以接受误差0.3 - 0.2 - 0.1 <= Number.EPSILON // true

class语法糖到底是怎么继承的?

function Super() {

this.a = 1;

}

function Child() {

// 属性继承

Super.call(this);

this.b = 2;

}

// 原型继承

Child.prototype = new Super();

const child = new Child();

child.a; // 1

正式代码的原型继承,不会直接实例父类,而是实例一个空函数,避免重复声明动态属性

const extends = (Child, Super) => {

const fn = function () {};

fn.prototype = Super.prototype;

Child.prototype = new fn();

Child.prototype.constructor = Child;

};

es6居然可以重复解构对象

const obj = {

a: {

b: 1

},

c: 2

};

const { a: { b }, a } = obj;

一行代码同时获取a和a.b。在a和b都要多次用到的情况下,普通人的逻辑就是先解构出a,再在下一行解构出b。

判断代码是否压缩居然也这么秀

function CustomFn() {}

const isCrashed = typeof https://www.360docs.net/doc/8b10734879.html, === 'string' && CustomFn.na me === 'CustomFn';

对象===比较的是内存地址,而>=将比较转换后的值

{} === {} // false

// 隐式转换 toString()

{} >= {} // true

intanceof的判断方式是原型是否在当前对象的原型链上面

function People() {}

function Man() {}

Man.prototype = new People();

Man.prototype.constructor = Man;

const man = new Man();

man instanceof People; // true

// 替换People的原型

People.prototype = {};

man instanceof People; // false

如果您用es6的class的话,prototype原型是不允许被重新定义的,所以不会出现上述情况

Object.prototype.__proto__ === null; // true

这是原型链向上查找的最顶层,一个null

parseInt太小的数字会产生 bug

parseInt(0.00000000454); // 4

parseInt(10.23); // 10

1 + null// 1

1 + undefined// NaN

Number(null) // 0

Number(undefined) // NaN

arguments和形参是别名关系

function test(a, b) {

console.log(a, b); // 2, 3

arguments[0] = 100;

arguments[1] = 200;

console.log(a, b); // 100, 200

}

test(2, 3);

但是您可以用use strict严格模式来避免这一行为,这样arguments就只是个副本了。

void是个固执的老头

void0 === undefined// true

void1 === undefined// true

void {} === undefined// true

void'hello' === undefined// true

void void0 === undefined// true

跟谁都不沾亲~~

try/catch/finally也有特定的执行顺序

function fn1() {

console.log('fn1');

return1;

}

function fn2() {

console.log('fn2');

return2;

}

function getData() {

try {

throw new Error('');

} catch (e) {

return fn1();

} finally {

return fn2();

}

}

console.log(getData());

// 打印顺序: 'fn1', 'fn2', 2

在try/catch代码块中,如果碰到return xxyyzz;关键词,那么xxyyzz会先执行并把值放在临时变量里,接着去执行finally代码块的内容后再返回该临时变量。如果finally中也有return aabbcc,那么会立即返回新的数据aabbcc。

是否存在这样的变量x,使得它等于多个数字?

const x = {

value: 0,

toString() {

return ++this.value;

}

}

x == 1 && x == 2 && x == 3; // true

通过隐式转换,这样不是什么难的事情。

clearTimeout和clearInterval可以互换~~~~使用吗

var timeout = setTimeout(() => console.log(1), 1000);

var interval = setInterval(() => console.log(2), 800);

clearInterval(timeout);

clearTimeout(interval);

答案是:YES。大部分浏览器都支持互相清理定时器,但是建议使用对应的清理函数。

下面的打印顺序是?

setTimeout(() => {

console.log(1);

}, 0);

new Promise((resolve) => {

console.log(2);

resolve();

}).then(() => console.log(3));

function callMe() {

console.log(4);

}

(async () => {

await callMe();

console.log(5);

})();

答案是:2, 4, 3, 5, 1

主线任务:2,4

微任务:3,5

宏任务:1

null是object类型,但又不是继承于Object,它更像一个历史遗留的bug。鉴于太多人在用这个特性,修复它反而会导致成千上万的程序出错。

typeof null === 'object'; // true

Object.prototype.toString.call(null); // [object Null]

null instanceof Object; // false

JavaScript常用知识点

1、GET和POST的区别,何时使用POST? GET:一般用于信息获取,使用URL传递参数,对所发送信息的数量也有限制,一般在2000个字符 POST:一般用于修改服务器上的资源,对所发送的信息没有限制。 GET方式需要使用Request.QueryString来取得变量的值,而POST方式通过Request.Form来获取变量的值, 也就是说Get是通过地址栏来传值,而Post是通过提交表单来传值。 然而,在以下情况中,请使用POST 请求: 无法使用缓存文件(更新服务器上的文件或数据库) 向服务器发送大量数据(POST 没有数据量限制) 发送包含未知字符的用户输入时,POST 比GET 更稳定也更可靠JavaScript是客户端和服务器端脚本语言,可以插入到HTML页面中,并且是目前较热门的Web开发语言。同时,JavaScript也是面向对象编程语言。 类似的基本题目还包括:JavaScript都有哪些类型?JavaScript是谁发明的?……2、列举Java和JavaScript之间的区别? Java是一门十分完整、成熟的编程语言。相比之下,JavaScript是一个可以被引入HTML页面的编程语言。这两种语言并不完全相互依赖,而是针对不同的意图而设计的。Java是一种面向对象编程(OOPS)或结构化编程语言,类似的如C ++或C,而JavaScript是客户端脚本语言,它被称为非结构化编程。

3. JavaScript和ASP脚本相比,哪个更快? JavaScript更快。JavaScript是一种客户端语言,因此它不需要Web服务器的协助来执行。另一方面,ASP是服务器端语言,因此总是比JavaScript慢。值得注意的是,Javascript现在也可用于服务器端语言(nodejs)。 4、什么是负无穷大? 负无穷大是JavaScript中的一个数字,可以通过将负数除以零来得到。 5、如何将JavaScript代码分解成几行吗? 在字符串语句中可以通过在第一行末尾使用反斜杠“\”来完成 例:document.write(“This is \a program”); 如果不是在字符串语句中更改为新行,那么javaScript会忽略行中的断点。

js基础知识

Js1k:用1k的代码做出炫目的效果。代码扩写 犀牛书 微信公众号:前端大全 1. ***变量 2. ***数据类型 一.***变量:内存中存储*一个*数据的存储空间,再起一个名字 何时使用:程序中反复使用的数据,都要先保存在变量中,再参与运算 如何使用:声明赋值取值 1. 声明:在内存中创建一个新变量 如何声明:var 变量名; 仅声明,但暂未赋值,默认值为undefined 变量命名:1. 不能以数字开头,仅能包含字母,数字和下划线 2. 不能用保留字:js中已经预先使用的关键字 比如:name X 3. 见名知意 4. 驼峰命名:第一个单词首字母小写, 之后每个单词首字母大写: 比如:backgroundColor,listStyleType 2. 赋值:将等号*右边*的数据,保存到等号*左边*的变量中 如何赋值:变量名=值;il *对已经包含值的变量赋新值,新值会替换旧值* 建议:1. 在声明同时,初始化变量的值 如何在声明同时初始化:var 变量名=值; 3. 取值:只要使用变量名,在运行时,会被自动替换为变量中的值 特殊情况:3种: 1. 只声明,但未赋值的变量,可任意使用 比如:var hb; console.log(hb); //undefined 2. 从未声明的变量,不能使用(取值)! 报错:ReferenceError: XXX is not defined 3. 未声明的变量,却可赋值!——其实和var不一样 强烈建议:必须用var声明变量 ***声明提前:在程序正式*执行前*,都会将var声明的变量提前到*当前脚本块*的顶部集中声明。再开始执行程序。***赋值留在原地*** 常量:一旦初始化,值不能改变的量 何时使用:程序中,一旦定义不可擅自改变的值,都要用常量保存 如何创建:const 常量名=值; 用作常量的名称,都要大写字母 强行修改常量的值,不会报错,但也无法修改成功!

javaScript重点知识总结

1、JavaScript 显示数据 JavaScript 可以通过不同的方式来输出数据: 使用window.alert()弹出警告框。 使用document.write()方法将内容写到HTML 文档中。 使用innerHTML写入到HTML 元素。 使用console.log()写入到浏览器的控制台。 实例: document.getElementById("demo").innerHTML = "段落已修改。"; document.write("

这是一个标题

");//write可以直接写入格式! 2、JavaScript 数据类型 var length = 16; // Number 通过数字字面量赋值var points = x * 10; // Number 通过表达式字面量赋值var lastName = "Johnson"; // String 通过字符串字面量赋值var cars = ["Saab", "Volvo", "BMW"]; // Array 通过数组字面量赋值var person = {firstName:"John", lastName:"Doe"}; // Object 通过对象字面量赋值 var cars=new Array(); cars[0]="Saab"; cars[1]="Volvo"; cars[2]="BMW"; 3、JavaScript事件

HTML 事件可以是浏览器行为,也可以是用户行为。 以下是HTML 事件的实例: HTML 页面完成加载。 HTML input 字段改变时。 HTML 按钮被点击。 右图是常见的事件(前面都有on) 事件有三种写法,举onclick为例: //后面再写函数实现方式。 4、JavaScript 字符串 var carname = "Volvo XC60"; var character = carname[7]; //字符串的索引从0 开始 JavaScript本身对单引号还是双引号没有区别。一般都用双引号,两个都存在时,再考虑。

JavaScript复习题

复习题1 一、选择题 1、写“Hello World”的正确javascript语法是 A. ("Hello World") B. "Hello World" C. ("Hello World") D. ("Hello World") 2、JS特性不包括( ) A.解释性 B.用于客户端 C.基于对象 D.面向对象 3、下列JS的判断语句中( )是正确的 (i==0)(i=0) i==0 then i=0 then 4、下列JavaScript的循环语句中( )是正确的 (i<10;i++) (i=0;i<10) i=1 to 10 (i=0;i<=10;i++) 5、下列的哪一个表达式将返回假 A.!(3<=1) B.(4>=4)&&(5<=2) C.(“a”==”a”)&&(“c”!=”d”) D.(2<3)||(3<2) 6、下列选项中,( )不是网页中的事件 7、有语句“var x=0;while(____) x+=2;”,要使while循环体执行10次,空白处的循环判定式应写为: A.x<10 B. x<=10 <20 <=20 8、JS语句 var a1=10; var a2=20; alert(“a1+a2=”+a1+a2) 将显示( )结果 +a2=30 +a2=1020+a2=a1+a2 9、将字串s中的所有字母变为小写字母的方法是( ) 、以下( )表达式产生一个0~7之间(含0,7)的随机整数. . floor()*8) 11、产生当前日期的方法是( ) (); () Date() Now() 12、如果想在网页显示后,动态地改变网页的标题( ) A.是不可能的 B.通过(“新的标题内容”) C. 通过=(“新的标题内容”) D. 通过(“新的标题内容”) 13、某网页中有一个窗体对象,其名称是mainForm,该窗体对象的第一个元素是按钮,其名称是myButton,表述该按钮对象的方法是()

Vue.js基础知识汇总

Vue.js 专注于MVVM 模型的ViewModel 层。它通过双向数据绑定把View 层和Model 层连接了起来。Vue.js和其他库相比是一个小而美的库,作者的主要目的是通过一个尽量简单的API 产生可反映的数据绑定和可组合的视图组件,感觉作者的思路非常清晰。 介绍 vue.js 是用来构建web应用接口的一个库 技术上,Vue.js 重点集中在MVVM模式的ViewModel层,它连接视图和数据绑定模型通过两种方式。实际的DOM操作和输出格式被抽象的方式到指令(Directives)和过滤器(Filters) 在哲学领域内,尽量让MVVM数据绑定API尽可能简单。模块化和可组合性也是重要的设计考虑。vue不是一个全面的框架,它被设计成简单的和灵活的。你可以用它快速原型,或混合和匹配与其他库定义前端堆栈。 Vue。js的API是参考了AngularJS、KnockoutJS Ractive.js Rivets.js。尽管有相似之处,我相信Vue.js提供一个有价值能够让你在现在的一些现有框架中舍取其价值即使你已经熟悉其中的一些术语,建议您通过以下概念的概述,因为你的这些术语的概念可能在Vue.js的下文中有所不同 概念概述 ViewModel 一个对象,同步模型和视图. 在Vue.js中,ViewModels是实例化的Vue的构造器或者是它的子类 var vm = new Vue({ /* options */ }) 这是主要的对象,你会与作为开发人员在使用Vue.js交互。更多细节请参阅Class: Vue. View 用户看到的实际HTML / DOM vm.$el // The View 当使用Vue.js时候,除了自己自定义的指令你几乎不会触碰到DOM的操作,当数据更新后视图的更新将会自动的触发,视图的更新可以很精确的到每一个testNode节点,他们也批处理和异步执行从而提供更好的性能。 Model 这是一个略微修改的Javascript对象 vm.$data // The Model 在Vue.js中,模型只是简单的Javascript对象,数据对象,你能够操控他们的属性和视图模型,观察他们的从而能获取通知后更改。Vue.js在data对象胡总用ES5的getter/setter 把属性转化了,它允许直接操作而不需要脏检查。 data对象在适当的时候会产生突变,所以修改它与通过引用修改vm.$data是一样的效果。这也方便了多个ViewModel实例观察同一块数据。 技术细节请看Instantiation Options: data. Directives 私有的HTML属性是告诉Vue.js做一些关于DOM的处理 <div v-text="message"></div> 这里的div元素有一个v-text的指令,值是message.意思是告诉Vue.js 保持这个div节点的内容与viewMode中的message属性同步 指令可以封装任意DOM操作。例如v-attr 操作一个属性元素,v-repeat克隆基于数组的

《JavaScript项目式实例教程》课程标准

《JavaScript项目式实例教程》课程标准 课程编号:02104 课程类型:非核心课程、一体化课程学时:72 适用对象:软件与信息服务专业二年级学生编制者:屹峰审核者: 编制日期: 2014-07-05 一、课程的性质1、课程定位 《JavaScript项目式实例教程》课程是计算机软件与信息服务专业的一门重要的专业课,定位于WEB技术开发工作岗位。它是WEB前端技术开发的必备课程,在整个课程体系中具有重要的作用。本课程的前导课程:静态网页设计、DIV+CSS布局。后续课程:网页美工、PHP 动态网页设计、C#程序设计与应用等。 2、课程任务 《JavaScript项目式实例教程》课程课程任务是培养网页设计、网页美工以及WEB综合开发的初、中级专业人才,通过本课程的学习,学生能掌握JavaScript语言的基本编程思想,并能熟练利用JavaScript控制WEB页面各级元素,实现WEB前端的验证、动态展示等任务。 二、职业活动 通过本课程的学习,使学生形成一定的学习能力、沟通与团队的协作能力,形成良好的思考问题、分析问题和解决问题的能力,养成良好的职业素养。遵守国家关于软件与信息技术的相关法律法规,形成关键性的软件开发与应用的能力。最终成为具备较全面的软件开发与信息服务的技术人才。 该课程涉及的知识是Web应用程序或前端开发人员必备的基本技能,职业活动与课程容的对应关系如下: Web前端开发岗位职业能力教学容(理实一体化课)模块化设计思想任务模块化(第1章)程序设计基本流程判断、循环结构(第2、3章)与基本对象的交互设计事件(第4章)事件高级应用(第8章)操作浏览器窗口窗口对象(第5章)操作Document 文档对象(第6章)操作DOM DOM对象(第7章)动画基础运动基础(第9章) 三、教学目标1、职业关键能力目标 (1)掌握JavaScript语言的基本语法及常用的置函数(2)掌握事件以及事件的触发机制(3)掌握BOM对象的常用属性和方法《JavaScript项目式实例教程》课程标准 3 (4)掌握文档对象的常用属性和方法(5)掌握Cookie对象的使用方法 (6)掌握DOM的概念以及利用DOM操作文档节点的方法(7)掌握事件流和事件绑定(8)掌握利用JavaScript设计缓冲运动的原理和方法2、职业专门能力目标 (1)通过完成相关的项目,掌握JavaScript语言的语法结构。 (2)通过完成相关的项目,掌握JavaScript各种置对象的使用方法和应用情境。 (3)通过完成相关的项目,寻找发现问题途径,学会解决问题的方法3、方法能力目标形成一定的学习能力、沟通与团队的协作能力,形成良好的思考问题、分析问题和解决问题的能力,养成良好的职业素养。遵守国家关于软件与信息技术的相关法律法规,形成关键性的软件开发与应用的能力。 四、课程容1、预备知识

Bootstrap知识简单归纳

Bootstrap 响应式实用工具---目前只适用于块和表切换 Bootstrap 字形图标(Glyphicons) 什么是字形图标(Glyphicons)? 字形图标(Glyphicons)是在Web 项目中使用的图标字体。 字形图标(Glyphicons)列表 点击这里,查看可用的字形图标(Glyphicons)列表 用法 如需使用图标,只需要简单地使用下面的代码即可。请在图标和文本之间保留适当的空间。 在线定制字形图标(Glyphicons) 点击这里,在线定制字形图标(Glyphicons)。 插入符 使用插入符表示下拉功能和方向。使用带有class caret 的 元素得到该功能。 关闭图标 使用通用的关闭图标来关闭模态框和警告框。使用class close 得到关闭图标。 快速浮动 您可以分别使用class pull-left 或pull-right 来把元素向左或向右浮动。下面的实例演示了这点。 如需对齐导航栏中的组件,请使用.navbar-left 或.navbar-right 代替。请查看Bootstrap 导航栏。 居中内容块 使用class center-block 来居中元素。

清除浮动 如需清除元素的浮动,请使用.clearfix class。 显示和隐藏内容 您可以通过使用class .show 和.hidden 来强行设置元素显示或隐藏(包括屏幕阅读器)。屏幕阅读器 您可以通过使用class .sr-only 来把元素对所有设备隐藏,除了屏幕阅读器。 Bootstrap 下拉菜单(Dropdowns) 对齐 通过向.dropdown-menu 添加class .pull-right 来向右对齐下拉菜单class="dropdown-menu pull-right" 标题 您可以使用class dropdown-header 向下拉菜单的标签区域添加标题 Bootstrap 按钮组 按钮组允许多个按钮被堆叠在同一行上。当你想要把按钮对齐在一起时,这就显得非常有用。您可以通过Bootstrap 按钮(Button)插件添加可选的JavaScript 单选框和复选框样式行为 Bootstrap 按钮下拉菜单 本章将讲解如何使用Bootstrap class 向按钮添加下拉菜单。如需向按钮添加下拉菜单,只需要简单地在在一个.btn-group 中放置按钮和下拉菜单即可。您也可以使用 来指示按钮作为下拉菜单。