javascript冷知识
本人很少写博客,所以文笔很不好,如果解释的不够清楚的,欢迎点评
1.+号(一元加操作符):
如果放在数值前的话,对数值不会产生任何影响,不过放在其他的数据类型前面的话,就等于调用number()将他转为数字,布尔值false被转为0,ture被转为1
如, +"1.1" = 1.1 ,对象则会调用它的valueof()或者toString()函数,然后再转为数值
2.parseInt:可以用它来指定数据的类型,如 parseInt("12", 8) // 10 第二个参数为进制
parseFloat: 只有一个参数:要转的字符串,只能转为十进制
3.一元减操作符:与+号的一样的原理,不过就是变为相反数
4.toString操作:
可以利用它将数值转为不同进制
ex: var i = 10; i.toString(16) // 'a' 转为十六进制
5. >> (右移)和<<(左移)操作都不会改变符号位,但是 >>> 则会连符号位一起移动
6.
逻辑或操作符 || 返回的是操作数,而不是true or false.
ex:
var a = "test";
var b = a || c // b = "test"
var b = null || a // b = "test"
7 将一个数值与一个字符串相加的话,等于把这个数值添加到字符串中
var result = "5" + 5; // result = "55"
将一个数值减去一个字符串的话,这个字符串会被转化为数字进行运算。
var result = 5 - "1" // result = 4
8. < 比较符
因此, 2 < "3" // true "3" > "23" // true
但是,任何与NaN比较的结果都返回false,如 'a' > 12 // false 'a' <= 12 // false
9.with语句:将代码的作用域设置到一个特定对象中,如
var ps = location.search
var hostName = location.hostname
var url = location.href
// 我们可以用with改为
with(location) {
var ps = search
var hostName = hostname
var url = href
}
10.javascript 没有重载函数。前一个函数会被最后一个覆盖掉
function test1() {
console.log("before");
}
function test1(params) {
console.log("after");
}
test1(); // after; 前面那个函数被覆盖掉了
可以用arguments.length获取输入的参数数目,arguments[i]来获取第i个参数
11.赋值运算的时候,若是基本类型的赋值,则等于创建了一个新值,若是引用类型(对象)的赋值,则两个会指向同一个对象
var i = 5;
var b = i;
i = 4// i = 4, b = 5
var obj1 = new Object();
obj2 = obj1;
obj1.t = "asd";
obj2.t // "asd" 两个指向同一个对象,所以obj1改变了,obj2也跟着改变
函数传参也是一样,基本类型就等于创建个新值,引用类型就会指向同一个对象,但是是按值传递,只不过只是指向的地址相同,如果在函数里面让他等于一个新对象的话,那么外面的不会受到影响
12 使用instance来判断对象是什么类型的 // 数组的话,可以用Array.isArray(value)的方法来判断
13.javascript没有块级作用域,因此
if (i = 1) { var result = "test" } console.log(result) // "test"
可以通过函数来解决这个问题,在函数内部定义的局部变量,外部访问不到
14.访问对象的属性的时候,可以通过.或者[],例如
var i = { name : "test" } i.name == i["name"]
如果属性名包括会导致语法错误的字符 或者属性名使用的是关键字或者保留字,则使用方括号方法。
person['first name'] = 'CJG' // 不能用.号运算符
15 Array.sort():
该函数会将数组的每一项转化字符串,然后再进行比较,这就会导致一个问题:
var values = [0,1,5,10,15] values.sort(); // 0, 1, 10, 15, 5
解决方法: 它可以接受一个函数参数,因此我们可以自己写一个比较函数:
function cmp(value1, value2) {return value2 - value1;}
然后values.sort(cmp) // 0, 1, 5, 10, 15
因此,我们可以自己写函数来决定它的排序方法
16 数组常用操作:
concat: 基于当前数组的内容,创建一个新的数组
var i = [1,2,3]
var b = i.concat[4,[6,8]] // [1,2,3,4,6,8]
slice: 基于当前数组的一或多个项创建新数组
var i = [1,2,3,4]
var b= i.slice(1) // [2,3,4]
var c = i.slice(1,3) // [2,3]
splice: 用来删除数据(前两个参数,删除的项的位置以及删除的数目)或者插入数据(三个参数,起始位置,0,以及要插入的项)或者替换(三个参数,起始位置,1,要插入的任意数量的项)
var i = [1,2,3,4]
var b = i.splice(0,1) // b = [1] i = [2,3,4]
17 函数内部,有两个特殊的对象:arguments 和 this, argument除了保存着函数参数之外,还有一个属性callee,这个属性指向拥有这个对象的函数。
例如,斐波那契数列可以这样写,我们用callee将他改变下
function factorial(num) {
if(num <= 1) {
return 1;
} else {
return num * factorial(num-1);
}
}
//改进
function factorial(num) {
if(num <= 1) {
return 1;
} else {
return num * arguments.callee(num-1);
}
}
这样做的好处是什么呢?在于,你无论你的函数名怎么变,这一段代码都能生效。
假设你这样写:
var trueFactorial = factorial;
factorial = funcion() {
return 0;
}
trueFactorial(5) // 如果我们用改进的版本,输出为120,否则,则为0
factorial(5) // 0
18.函数有两个非继承(不在prototype里)的方法:apply和call
apply接受两个参数,第一个是运行这个函数的对象(作用域),第二个是一个参数数组(也可以是一个arguments对象),指的是这个函数运行所需要的参数
function sum(num1, num2) {
return num1 + num2;
}
function test(num1, num2) {
return sum.apply(this, arguments); //和下面的代码结果是一样的
//return sum.apply(this, [num1,num2])
}
test(1,2) // 3 由于是在全局作用域用的,这个时候this是window对象
call 和apply的作用是相同的,第一个参数是一样的,不同的是,参数是直接传递给函数,这个时候test的代码应该改为
return sum.call(this, num1, num2);
当然,他们的作用不只局限于而已。他的作用在于,我们可以扩展他的作用域。如
function sayColor() {
console.log(this.color);
}
var color = "red";
var t = { color : "blue" }
sayColor.call(this); // red
sayColor.call(t); // blue
19.
20.ECMAscript有两种属性:数据属性和访问器属性,数据属性有:
要改变属性默认的特征,必须使用ECMAscript5的Object.defineProperty().
具体用法如下:
(1)
var person = { }
Object.defineProperty(person, "name", {
writeable: false, // 让这个属性不能重写,只读
value: "CJG“ // 给属性赋一个默认值
}
console.log(person.name) // 'CJG'
person.name = 'ZHT';
console.log(person.name) // 'ZHT' 只读,不能改
(2)
var person = { }
Object.defineProperty(person, "name", {
configurable: false, // 让这个属性不能被删除
value: "CJG“ // 给属性赋一个默认值
}
console.log(person.name) // 'CJG'
delete person.name = 'ZHT';
console.log(person.name) // 'ZHT' 只读,不能改
21.在创建自己类时候,最好使用动态原型模式,如
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
//定义方法的做法
if (typeof this.sayName != function) {
Person.prototype.sayName = function() {
alert(this.name)
}
}
}
var person1 = new Person("CJG", 20, 'student');
var person2 = new Person("ZHT", 20, "student");
person1.sayName(); // CJG
person1.name = "CJG11"
person1.sayName(); // CJG11
person2.sayName(); // ZHT
优点:每一个实例都有自己的一些变量,但是他们又共享同一个方法,这样就可以节省空间。
22.对象继承:
组合继承方法:
function Super(name) {
this.name = name;
this.color = ['blue', 'red', 'green'];
}
super.sayName = function() {
console.log(this.name);
}
function sub(name, age) {
Super.call(this, name);
this.age = age;
}
sub.prototype = new Super(); // sub类的原型为Super的实例
sub.prototype.sayAge = function() {
console.log(this.age);
}
var subtest = new sub("CJG", 20);
subtest.sayAge(); // 20
subtest.sayName(); // name
subtest.color.push("pink") // ['blue', 'red', 'green', 'pink'];
var subtest1 = new sub("ZHT", 20)
console.log(subtest1.color) // ['blue', 'red', 'green']
好处:子类继承了父类的方法,并且每一个子类都拥有父类的属性副本,属性不共享,方法共享
缺点: 调用了两次父类的构造函数(第一次在sub的构造函数上,第二个在sub.prototype赋值上)。实际上,子类拥有两个版本的父类的属性副本,第一个版本在subtest上,第二个版本在subtest.prototype上,第一个版本掩盖了第二个版本
原型链图如下:
改进方法:
寄生组合式继承:
23.函数表达式的问题:
//可以正常运行
sayHi(); // 代码在执行前,会先读取函数声明,也就是会先找到函数声明在来执行这一段代码
function sayHi() {
console.log("Hi"); // 这个是函数声明
}
//报错
sayHi();
sayHi = function() {
console.log("Hi"); // 这个是函数表达式
}
24.闭包:指有权访问另一个函数作用域的变量的函数
function sayName() {
name = "CJG"
return function() {
console.log(name);
}
}
var s = sayName();
s(); // CJG
在上面这个例子中,sayName中的匿名函数可以访问sayName的变量(访问了另一个函数作用域的变量),一般来说,一个函数运行完后,他的作用域就会被移除,所以name应该是访问不到的。可是为什么能正常运行呢?
原因:在闭包中,由于匿名函数调用了sayName里的变量,将它的变量加到自己的作用域内,所以如果它存在的话,sayName的变量就不会消失.我们可以通过将s=null来解除对匿名函数的引用,以此来释放内存
闭包的问题:
//这个函数的作用是,创建一个函数数组,第i个函数输出i
function sayI() {
var result = [];
for (var i = 0; i < 10; i++)
result[i] = function() {
console.log(i);
}
return result;
}
var result = sayI();
result[3](); // 10
Why?为什么不是输出3?原因是,每一个函数输出的值为i,而i最后循环变为10.因此,每一个函数的输出都是10
解决:
function sayI() {
var result = [];
for (var i = 0; i < 10; i++)
result[i] = function(num) {
return function() {
console.log(num);
}
}(i)
return result;
}
var result = sayI();
result[3](); // 3
在这里,我们再次用了闭包,将i的值传递给这个函数.
除此之外,闭包还存在一个问题:占用很多内存
function assignHandler() {
var element = document.getElementById("content");
element.onclick = function() {
console.log(element.id);
}
}
调用这个函数的时候,为"content"这个元素增加了一个onclick事件。这看起来没什么问题,但是,由于在那个匿名函数里面调用了另一个函数的变量(element.id),因此构成了闭包。这就导致了,element这个变量无法被回收。
解决:
function assignHandler() {
var element = document.getElementById("content");
var id = element.id;
element.onclick = function() {
console.log(id);
}
element = null;
}
由于只要匿名函数有调用到assignHandler的变量,因此assignHandler里面的所有变量都不会消失。因此我们可以通过设置element=null来手动回收他
25.window对象:所有在全局作用域声明的变量,函数都会成为他的变量和函数。不过,在全局变量里声明的变量或者函数不能删除,而在window上声明的可以删除。
26.
javascript冷知识的更多相关文章
- 前端不为人知的一面--前端冷知识集锦 前端已经被玩儿坏了!像console.log()可以向控制台输出图片
前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Quora上一个帖子,瞬间又GET了好多前 ...
- 前端不为人知的一面–前端冷知识集锦 原文地址(http://web.jobbole.com/83473/);
前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Quora上一个帖子,瞬间又GET了好多前 ...
- 转:前端冷知识(~~some fun , some useful)
前端不为人知的一面——前端冷知识集锦 前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Qu ...
- web 前端冷知识
前端已经被玩儿坏了!像console.log()可以向控制台输出图片等炫酷的玩意已经不是什么新闻了,像用||操作符给变量赋默认值也是人尽皆知的旧闻了,今天看到Quora上一个帖子,瞬间又GET了好多前 ...
- 这些鲜为人知的前端冷知识,你都GET了吗?
背景 最近公司项目不多,比较清闲,划水摸鱼混迹于各大技术博客平台,瞬间又GET了好多前端技能,一些属于技巧,一些则是闻所未闻的冷知识,一时间还消化不过来,不由的发出一声感叹! 前端可真是博大精深 于是 ...
- Javascript基础知识总结一
Javascript基础知识总结一 <!DOCTYPE html> <html> <head lang="en"> <meta chars ...
- .Net冷知识之动态查找类型时的程序集路径问题
今天就说说.Net中通过反射取得某个类型时,我们怎么知道这个类型在硬盘上的哪个角落?比如说,假如我们需要要求服务端动态载入某个数据源,那服务端怎么知道数据源在哪? 网上大部分的教程都写着,可以使用As ...
- 学习javascript基础知识系列第二节 - this用法
通过一段代码学习javascript基础知识系列 第二节 - this用法 this是面向对象语言中的一个重要概念,在JAVA,C#等大型语言中,this固定指向运行时的当前对象.但是在javascr ...
- 学习javascript基础知识系列第三节 - ()()用法
总目录:通过一段代码学习javascript基础知识系列 注意: 为了便于执行和演示,建议使用chrome浏览器,按F12,然后按Esc(或手动选择)打开console,在console进行执行和演示 ...
随机推荐
- Orion Network Performance Monitor 软件在网络管理中的应用
Orion Network Performance Monitor 软件在网络管理中的应用 Orion Network Performance Monitor是完全的带宽性能和故障管理软件 ...
- Unity2D Keynote
[Unity2D Keynote] 1.File Format Accepted by Unity 2.By double-clicking an object in Hierachy, you no ...
- HDU 5164Matching on Array(AC自动机)
这是BC上的一道题,当时比赛没有做,回头看看题解,说是AC自动机,想着没有写过AC自动机,于是便试着抄抄白书的模板,硬是搞了我数个小时2000ms时限1800过了= = ! 这里就直接贴上BC的结题报 ...
- junit学习(3.x)
自动化测试 测试所有测试类 import junit.framework.TestCase; import junit.framework.Assert; /** *测试类必须要继承TestCase类 ...
- oracle客户端安装及Plsql devloper连接
1)安装Oracle 11g 64位 2)安装32位的Oracle客户端( instantclient-basic-win32-11.2.0.1.0)下载instantclient-basic-win ...
- MyArrayList——实现自己的ArrayList!
注:转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5965205.html ArrayList是我们常用的集合类之一,其实它的实现机制很简单,底层还是使用了一个 ...
- Linux下修改hostname
我维护两三个机房的数十台机器,开发用机器,运营用机器,自己工作机器也是ubuntu,有时开很多ssh,干的还是同样的事情,很容易搞混.所以需要一目了然的知道某台机器的情况,避免犯晕.这就需要修改主机名 ...
- UI:字典的两种取值的区别
字典的两种取值的区别 (objectForKey: 和 valueForKey )参考 一般来说 key 可以是任意字符串组合,如果 key 不是以 @ 符号开头,这时候 valueForKey: 等 ...
- tab栏切换的特殊效果(类似网易的登陆栏效果)
代码显示效果如上图所示: 需求说明: 在实际需求中,会遇到这样的情况:不仅是要展示选项卡的内容,而且还有可能在选项卡中需求顾客填写相关内容,而这些内容是顾客如果想了解更深层次的,就会继续填写右边的内容 ...
- UVA1151
//感觉刘汝佳老师的思维真的太厉害了orz /*摘录书上的一段话: 只需一个小小的优化即可降低时间复杂度:先求一次原图(不购买任何套餐)的最小生 成树,得到n-1条边,然后每次枚举完套餐后只考虑套餐中 ...