搬砖,原文地址:http://segmentfault.com/a/1190000002911253

callee和caller

function inner(){
console.log(arguments.callee);//指向拥有这个arguments对象的函数,即inner()
console.log(arguments.callee.caller);//这个属性保存着调用当前函数的函数的引用,即outer()
console.log(inner.caller);//[Function: outer]
} function outer(){
inner();
}
outer();

callee放回正在执行的函数本身的引用,它是arguments的一个属性
caller 返回一个函数的引用,这个函数调用了当前的函数。

严格模式下,不允许访问arguments.calleearguments.caller属性,主要体现在arguments.[[Get]]内部方法

严格模式下,arguments,arguments.callee,arguments.caller,arguments.callee.caller也不允许再被赋值。如下代码所示:

'use strict';
// 两次都是1
void function fn(a) {
console.log(arguments[0]);
a = 2;
console.log(arguments[0]);
}(1); //function(){}(); 会运行错误, 如下可以正确被运行. void function(){
console.log('hi');//hi
}();

在使用立即执行的函数表达式时,可以利用 void 运算符让 JavaScript 引擎把一个函数识别成函数表达式而不是函数声明(语句)。

实参和形参

var add = function (a,b) {
console.log(arguments.length);//3,表示实参长度
console.log(arguments.callee.length);//2,表示形参长度
}; add(1,2,3);

Array.prototype.slice.call(arguments)

slice有两个用法,一个是String.slice,一个是Array.slice,第一个返回的是字符串,第二个返回的是数组。

Array.prototype.slice.call(arguments)能够将arguments转成数组,那么就是arguments.toArray().slice();

因为arguments并不是真正的数组对象,只是与数组类似而已,所以它并没有slice这个方法,而Array.prototype.slice.call(arguments)可以理解成是将arguments转换成一个数组对象,让arguments具有slice()方法。 比如:

var arr = [1,2,3,4];
console.log(Array.prototype.slice.call(arr,2));//[3,4]

同样,还有Array.prototype.forEach.call()forEach() 方法让数组的每一项都执行一次给定的函数。

String()

我们可以用String()来确定某一变量是否是null或者undefined

var a , b = null;
String(a);//undefined
String(b);//null

直接调用String()作为方法时,将会执行类型转换,返回经过toString(value)得到的字符串字面量(与new String()不同),或者空字符串('').

window 对象

 <script>
(function () {
var root = this;
console.log(root);//即window对象
})();
</script>

打开控制台,你可以看到window对象的一系列属性和方法:

new function

var a = function () {};
console.log(typeof a);//function var b = new function () {};
console.log(typeof b);//object var c = new Function ();
console.log(typeof c);//function

new function 是一个JavaScript中用户自定义的对象

var obj = function (name) {
this.name = name;
};
var b = new obj('trigkit4');
console.log(b.name);

js中的false和true

//false
console.log(Boolean(''));//false
console.log(Boolean(null));//false
console.log(Boolean(undefined));//false
console.log(Boolean(0));//false
console.log(Boolean(false));//false
console.log(Boolean(NaN));//false //true
console.log(Boolean(' '));//true
console.log(Boolean('NaN'));//true

除了false,null,undefined,空字符串'',数字0和NaN以外,其他所有值都被当做是真,包括true,字符串""里包含的值,以及所有对象。

valueOf() 和 toString()

valueOf()toString()方法是所有ECMAScript对象拥有的内置方法。操作对象时,valueOf()toString()会被隐式的调用。

//valueOf()
console.log(Object.valueOf());//[Function: Object]
console.log(Object.prototype.valueOf());//{} var boo = new Boolean(1);
console.log(boo.valueOf());//true var bar = Boolean(0);
console.log(bar.valueOf());//false var str = String("trigkit4");
console.log(str.valueOf());//trigkit4 console.log(null.valueOf());//TypeError
console.log(undefined.valueOf());//TypeError //toString()
console.log(Object.prototype.toString());//[object Object]
console.log(Object.toString());//function Object() { [native code] }
Object.prototype.toString.call(null);//[object Null]
Object.prototype.toString.call(undefined);//[object Undefined]
{a: 'b'}.toString();//[object Object]

valueOf()方法的目的是将对象转换成最有意义的原始值([[PrimitiveValue]])。即ECMAScript的5种基本类型中的三种,布尔值、数字、字符串

valueOf方法被调用时,会调用内置的ToObject,并将this作为参数传进去。ToObject检测会根据参数类型进行数值的转换:

Undefined - 抛出TypeError异常
Null - 抛出TypeError异常
Boolean - 创建一个Boolean对象,调用ToBoolean生成[[PrimitiveValue]]
Number - 创建一个Number对象,调用ToNumber生成[[PrimitiveValue]]
String - 创建一个String对象,调用ToString生成[[PrimitiveValue]]
Object - 对象本身

ECMAScript对象的大多数操作的转换结果是字符串,这两个方法的结果是相同的。但是如果操作的对象为NumberBoolean或者Date,结果就不同了。

var foo = {
toString: function () {
return "foo";
},
valueOf: function () {
return 5;
}
}; console.log(foo + "bar"); // 5bar
console.log([foo, "bar"].join("")); // foobar

在这个上下文环境中,我们使用"+"操作符来使字符串连接,但是,foo并没有使用toString来转换成字符串,它使用valueOf转换成一个number,这并不是我们想要的,
但它是如何工作的,这是+运算符的算术和字符串连接超载的副作用。"+"操作符有一个明确的处理过程:

1.评估左手侧,并得到该值。
2.评估右手侧,并获得该值。
3.同时在左手和右手侧调用ToPrimitive(无提示)
4.如果任何原始值是一个字符串,然后跳到7。
5.在这两个值调用ToNumber。
6.返回值的总和。
7.在这两个值调用toString。
8.返回的值连接起来

setInterval和setTimeout

alert(1);
setTimeout("alert(2)", 0);
alert(3);

执行顺序为:1,3,2,虽然延时了0ms

setTimeout 0  //正常情况下javascript都是按照顺序执行的。但是我们可能让该语句
后面的语句执行完再执行本身,这时就可以用到setTimeout延时0ms来实现了。

cookie的创建和删除

cookie可以跨越一个域名下的多个网页,但不能跨越多个域名使用。

document.cookie = “user = 值;expires = 过期时间;path = 路径访问;
domain = 域名访问;secure = 安全的https限制通信"

cookie的创建方式

设置cookie我们一般都封装成一个函数:

function addCookie(sName,sValue,day) {
var expireDate = new Date();
expireDate.setDate(expireDate.getDate()+day);;
//设置失效时间
document.cookie = escape(sName) + '=' + escape(sValue) +';
expires=' + expireDate.toGMTString();6 //escape()汉字转成unicode编码,toGMTString() 把日期对象转成字符串
}

删除cookie

为了删除一个cookie,可以将其过期时间设定为一个过去的时间,例如:

//获取当前时间
var date=new Date();
//将date设置为过去的时间
date.setTime(date.getTime()-10000);
//将userId这个cookie删除
document.cookie="userId=828; expires="+date.toGMTString();

给cookie设置终止日期

到现在为止,所有的cookie都是单会话cookie,即浏览器关闭后这些cookie将会丢失,事实上这些cookie仅仅是存储在内存中,而没有建立相应的硬盘文件。
在实际开发中,cookie常常需要长期保存,例如保存用户登录的状态。这可以用下面的选项来实现:

document.cookie="userId=828; expiress=GMT_String";

其中GMT_String是以GMT格式表示的时间字符串,这条语句就是将userId这个cookie设置为GMT_String表示的过期时间,超过这个时间,cookie将消失,不可访问。例如:如果要将cookie设置为10天后过期,可以这样实现:

<script language="JavaScript" type="text/javascript">
//获取当前时间
var date=new Date();
var expiresDays=10;
//将date设置为10天以后的时间
date.setTime(date.getTime()+expiresDays*24*3600*1000);
//将userId和userName两个cookie设置为10天后过期
document.cookie="userId=828; userName=hulk; expires="+date.toGMTString();
</script>

对象和函数可以如数组一样,用属性名或方法名作为下标来访问:

对象的创建

//对象的创建
function MyFunc(){}
var obj1 = new MyFunc();//使用new操作符,借助MyFun函数,就创建了一个对象
var obj2 = new MyFunc;//函数也可以没有括号,但仍将调用该函数

可以把上面的代码改写成这种等价形式:

function MyFunc(){};
var obj1 = {};//创建一个对象
MyFunc.call(obj1);//将obj1对象作为this指针调用MyFunc函数

作用域

通过自执行的匿名函数你可以把所有原本属于全局的变量都隐藏起来:

//创建一个新的匿名函数,作为包装
(function () {
//变量原本应该是全局的
var msg = "Thanks for visiting"; window.onunload = function () {
console.log(msg);
};
})();

上下文对象是通过this变量体现的,这个变量永远指向当前代码所处的对象中。

var obj = {
yes : function(){
//this == obj
this.val = true;
},
no : function(){
this.val = false;
}
};
console.log(obj.val == null);//true
//执行了yes函数后,将val属性与'obj'对象关联起来
obj.yes();
console.log(obj.val == true);//true

String 原型方法的扩展

//公共正则表达式处理函数
String.prototype.Regular = function(reg){
var result = true;
if(this.length > 0){
if(!reg.test(this)){
result = false;
}
}
return result;
} //.trim()方法
String.prototype.trim = function () {
return this.replace(/(^\s*)|(\s*$)/g,'');
};

^表示字符串必须以后面的规则开头,而(^\s*) 表示的就是以0个空格或者多个空格开头,后面的(\s*$) 的意思就是, 以0个空格或者多个空格结尾。

 //判断输入内容是否为空
String.prototype.isNull = function(){
return this.trim().length == 0 ? true : false;
} //判断输入的字符是否为英文字母\数字\下划线
String.prototype.isVersion = function(){
var reg = /^([a-zA-Z_])([a-zA-Z0-9_.])*$/;
return this.Regular(reg);
} // 判断输入的字符串,不包括单引号
String.prototype.isString = function(){
var reg = /^[^']*$/;
return this.Regular(reg);
} //判断输入的字符是否为英文字母
String.prototype.isLetter = function(){
var reg = /^[a-zA-Z]+$/;
return this.Regular(reg);
}

constructor属性

function User(){}
var me = new User();
console.log(me.constructor);//[Function: User] //用前一个对象的Constructor引用来创建一个新的User对象
var you = new me.constructor();
console.log(me.constructor == you.constructor);//true

Object.create

function Parent(){}
var o = Object.create(Parent.prototype);
console.log(o instanceof Parent);//true
console.log(o instanceof Object);//true
console.log(Object.prototype.toString.call(o));//[object Object]

“数据属性”是可获取且可设置值的属性。 数据属性描述符包含 value 特性,以及 writable、enumerable 和configurable 特性。 如果未指定最后三个特性,则它们默认为 false

function Parent(){}
var o = Object.create(Parent);
console.log(o instanceof Parent);//false
console.log(o instanceof Object);//true

另外一个实例

var book1 = {
title:"JS高级程序设计",
pages : 1001,
getTitle:function(){
console.log(this.title);
}
};
var book2 = Object.create(book1,{
//title会成为所创建对象的数据属性
title:{
configurable:true,
enumerable:true,
value:"JS权威指南",
wratable:true
}
});
book1.getTitle(); //"JS高级程序设计"
book2.getTitle(); //"JS权威指南" console.log(book1.hasOwnProperty("getTitle")); //true
console.log('pages' in book2); //true
console.log(book2.hasOwnProperty("getTitle")); //false
console.log(book1.isPrototypeOf(book2));//true

再看另一个例子:

function Constructor(){}
obj = new Constructor();
// 上面的一句就相当于:
obj = Object.create(Constructor.prototype);
console.log(obj);//{}
console.log(Object.create(Constructor.prototype));//{} console.log(obj instanceof Constructor);//true
console.log(Constructor.prototype.isPrototypeOf(obj));//true var foo;
foo = {};
// 以字面量方式创建的空对象就相当于:
foo = Object.create(Object.prototype);

另外:

console.log(Object.prototype);//{}
console.log(Object.create(Object.prototype));//{}

通过Object.create(Object.prototype) 创建的实例对象就继承了Object原型下的属性和方法。

javascript所有function类型的对象都有一个prototype属性。这个prototype属性本身又是一个object类型的对象,原型对象都包含一个指向构造函数的指针,而每一个实例也都包含一个指向原型对象内部的指针。

参考:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Glob...

prototype

function User(){}

var u1 = new User();
console.log(u1.prototype);//使用对象实例无法访问到prototype
console.log(User.prototype);//{},使用构造函数名访问prototype
console.log(u1.__proto__);//{},使用对象实例访问prototype的指针 //使用字面量的方式创建原型对象,这里{}就是对象
User.prototype = {
name : "trigkit4",
age : 22
};

使用构造函数创建原型对象和使用字面量创建对象在使用上基本相同,但还是有些区别,字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反

function User(){}
User.prototype = {
name : "trigkit4",
age : 22
};
var u1 = new User();
console.log(u1.constructor);//function Object() {[native code]}
console.log(u1 instanceof User);//true
console.log(u1.constructor == User);//false
console.log(u1.constructor == Object);//true //如果想让字面量方式的constructor指向实例对象,可以这么做:
User.prototype = {
constructor : User;
}

字面量方式为什么constructor会指向Object?因为User.prototype = {};这种写法其实就是创建了一个新对象:

function User(){}

User.prototype = {
constructor : User
};
var u1 = new User();
console.log(User.constructor);//[Function: Function]
console.log(u1.constructor == User);//true

另一个例子:

(function () {

        console.log(Object.prototype);//{}
console.log(Array.prototype);//[]
console.log(Array.prototype.push);//[Function: push]
console.log(Function.prototype);//[Function: Empty]
console.log(Function.prototype.bind);//[Function: bind] })();

Object.prototype.toString

toString()方法被调用时,会执行下面的操作步骤:

如果this的值为undefined,则返回"[object Undefined]".
如果this的值为null,则返回"[object Null]".
让O成为调用ToObject(this)的结果.
让class成为O的内部属性[[Class]]的值.
返回三个字符串"[object ", class, 以及 "]"连接后的新字符串.

由于 JavaScript 中一切都是对象,任何都不例外,对所有值类型应用Object.prototype.toString.call()

方法结果如下:

console.log(Object.prototype.toString.call(123)) //[object Number]
console.log(Object.prototype.toString.call('123')) //[object String]
console.log(Object.prototype.toString.call(undefined)) //[object Undefined]
console.log(Object.prototype.toString.call(true)) //[object Boolean]
console.log(Object.prototype.toString.call({})) //[object Object]
console.log(Object.prototype.toString.call([])) //[object Array]
console.log(Object.prototype.toString.call(function(){})) //[object Function]


所有类型都会得到不同的字符串,几乎完美。
JavaScript中,想要判断某个对象值属于哪种内置类型,最靠谱的做法就是通过Object.prototype.toString方法.

面向对象

下面是来自Prototype.js的一段代码:

//创建一个名为"Class"的全局对象
var Class = {
//它只有一个函数,其作用是创建一个新的对象构造函数
create: function(){
//创建一个匿名的对象构造函数
return function () {
//调用它本身的初始化方法
this.initialize.apply(this,arguments);
}
}
}; //给Object对象添加一个新的静态方法,它的作用是把属性从一个对象复制到另一个中
Object.extend = function (destination,source) {
//遍历所有要扩展的属性
for(property in source){
//然后将他们添加到目标对象中
destination[property] = source[property];
}
};

成员操作符

function aFunc(){}//或者var aFunc = function(){};

aFunc.oProperty = "函数的一个属性";
aFunc.aMethod = function(){
console.log("函数的一个方法");
}; console.log(aFunc["oProperty"]);//将函数当成数组以属性名作为下标来访问属性
console.log(aFunc["aMethod"]());//将函数当数组以方法名作为下标来调用方法 //遍历函数的所有属性和方法
for(var s in aFunc){
console.log(s + "is a "+typeof(aFunc[s]));
}

特权方法与私有方法

function Constructor(msg){
this.Message = msg; //私有属性
var separator = '-';
var owner = this; //私有方法
function alertMessage(){
console.log(owner.Message);
}
alertMessage(); //特权方法(也是公有方法)
this.aptMessage = function (str) {
this.Message += separator + str;
alertMessage();
}
} //公有方法
Constructor.prototype.clearMessage = function (str) {
this.Message = '';
}; //静态属性
Constructor.name = 'trigkit4'; //静态方法
Constructor.alertName = function (name) {
console.log(this.name);
};

特权方法是指在构造函数的作用域中使用this关键字定义的方法;与私有方法不同,特权方法能够被公开访问,而且还能够访问私有成员。

由于私有和特权成员在函数的内部,因此它们会被带到函数的每个实例中。
公有的原型成员是对象蓝图的一部分,适用于通过new关键字实例化的该对象的每个实例 静态成员只适用于对象的一个特殊实例

使用对象字面量语法来向prototype属性添加所有公有成员:

function Constructor(){
//私有和特权成员
} //公有方法
Constructor.prototype = {
propertyA: 'value1',
propertyB: 'value2',
methodA: function(){},
methodB: function(){}
};

删除不要的节点

DOM 元素在浏览器中所占用的空间是非常大的,要及时回收不用的节点:

var node = parentNode.removeChild(node);

node = null;//设置为空,释放空间
CollectGarbage();//IE,回收资源

关于原生js的一些研究的更多相关文章

  1. 原生js的一些研究和总结(1)

    数据类型 基本类型值包括: undefined,null,Boolean,Number和String,这些类型分别在内存中占有固定的大小空间,它们的值保存在栈空间,我们通过按值来访问的. 引用类型包括 ...

  2. 原生JS研究:学习jquery源码,收集整理常用JS函数

    原生JS研究:学习jquery源码,收集整理常用JS函数: 1. JS获取原生class(getElementsByClass) 转自:http://blog.csdn.net/kongjiea/ar ...

  3. 再谈React.js实现原生js拖拽效果

    前几天写的那个拖拽,自己留下的疑问...这次在热心博友的提示下又修正了一些小小的bug,也加了拖拽的边缘检测部分...就再聊聊拖拽吧 一.不要直接操作dom元素 react中使用了虚拟dom的概念,目 ...

  4. React.js实现原生js拖拽效果及思考

    一.起因&思路 不知不觉,已经好几天没写博客了...近来除了研究React,还做了公司官网... 一直想写一个原生js拖拽效果,又加上近来学react学得比较嗨.所以就用react来实现这个拖 ...

  5. 【前端性能】必须要掌握的原生JS实现JQuery

    很多时候,我们经常听见有人说jquery有多快多快.在这个各种类库满天飞的时候,不得不说的是,能有原生JS快吗? 是的,明显原生JS要更快,因为诸如JQuery这样的库必须要兼容各种浏览器和低版本和许 ...

  6. 原生js动画效果(源码解析)

    在做页面中,多数情况下都会遇到页面上做动画效果,大部分都是用jquery来实现动画,今天正好看到一篇原生js实现动画效果的代码,特分享在此. 原文地址:http://www.it165.net/pro ...

  7. 原生Js 两种方法实现页面关键字高亮显示

    原生Js 两种方法实现页面关键字高亮显示 上网看了看别人写的,不是兼容问题就是代码繁琐,自己琢磨了一下用两种方法都可以实现,各有利弊. 方法一 依靠正则表达式修改 1.获取obj的html2.统一替换 ...

  8. JQuery&原生js ——实现剪刀石头布小游戏

    前言 jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库( 或JavaScript框架).jQuery设计的宗旨是“write L ...

  9. 原生JS插件(超详细)

    作为一个前端er,如果不会写一个小插件,都不好意思说自己是混前端界的.写还不能依赖jquery之类的工具库,否则装得不够高端.那么,如何才能装起来让自己看起来逼格更高呢?当然是利用js纯原生的写法啦. ...

随机推荐

  1. 安装Android SDK和ADT步骤和遇到的问题

    http://894503895.diandian.com/post/2012-05-16/18695648 1.安装eclipse.下载地址:http://www.eclipse.org/downl ...

  2. js让iframe高度自动

    HTML: <iframe id="yb_if" width="940px" src="连接" frameborder=0 allow ...

  3. mysql中游标的使用

    BEGIN #遍历占领野地表还原军队 # and cityid=cityid) ,) ;#occupyWild表的TroopsId ,) ;#occupyWild表的CityId ,) ;#occup ...

  4. 使用SVN进行项目版本管理

    1.摘要 本文描述了利用SVN进行项目版本管理的方法,涉及项目版本号命名规则.SVN目录结构.第三方代码库的管理.版本创建.发布.修订.合并等行为的方法和原则. 2.版本号命名规则 版本号采用主版本号 ...

  5. Java多线程之线程中断

    该例子说明,Sleep可以被中断,但是I/O和synchronized不能被中断. package Thread.Interrupting; import java.io.IOException; i ...

  6. U盘安装Linux CentOS 6.5 64位操作系统(来自互联网)

    从centOS6.5开始直接把iso文件写入u盘就行了. 方法1:windows平台:1.用UltraISO打开iso(如:CentOS-6.5-x86_64-bin-DVD1.iso)2.然后点“启 ...

  7. c#创建、保存excel正常执行

    源地址:http://blog.csdn.net/hui_shixu/article/details/5785029

  8. [Java] 读写字符串数据

    package test.stream; import java.io.FileInputStream; import java.io.FileNotFoundException; import ja ...

  9. Regex 例

    密码复杂度:数字英文符号Regex r = new Regex("^(?:(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])|(?=.*[A-Z])(?=.*[a-z])(? ...

  10. poj 1007 (nyoj 160) DNA Sorting

    点击打开链接 DNA Sorting Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 75164   Accepted: 30 ...