popcorn丫

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

一、变量提升

console.log(a); //undefined    
var a = 0;

以上代码段并不会报错,js中存在变量提升,会将变量的声明提升至文件的顶部,形式如下。

var a;
console(a);
a = l;

函数会不会存在变量提升呢?答案是显然的。

f();
function f(){}

表面上好像是f()在声明前已经被调用了,由于变量提升f()被提升到了代码头部,但是采用复制语句定义函数会报错。

f();
var f = function(){};
//TypeError: undefined is not a function

/*
because:
var f;
f();
f = function(){}
*/

二、label

var a = 0;
loop:
for(let i=0;i<10;i++){
    for(let j=0;j<10;j++){
        a++;
        break loop;
    }
}
console.log(a); //1

以上loop为一个label,label多用来break或continue跳出代码块。

三、null与undefined

null与undefined在if语句中被转换为false。

null是一个表示为“空”的对象,它的出生较早(1995),根据C语言的传统,可以自动转换为0.

Number(null); //0
null+5; //5

undefined表明此处无定义的原始值

Number(undefined); //NaN
undefined+6; //NaN

如果JavaScript预期某个位置应该是布尔值,以下值会转换为false: undefined, null, false, 0, NaN, ""或''(空字符串);而其他值都是为true.

NaN不是独立的数据类型,是一个特殊的数值,数据类型仍然属于Number。

四、console

var languages = [
  { name: "JavaScript", fileExtension: ".js" },
  { name: "TypeScript", fileExtension: ".ts" },
  { name: "CoffeeScript", fileExtension: ".coffee" }
];

console.table(languages);

console.table()可以将对象以表格的形式打印。

console.time(), console.timeEnd()计算时间

五、defineProperty

var extend1 = function (to, from) {
  for (var property in from) {
    if (!from.hasOwnProperty(property)) continue;
    Object.defineProperty(
      to,
      property,
      Object.getOwnPropertyDescriptor(from, property)
    );
  }

  return to;
}

var extend2 = function (to, from) {
  for (var property in from) {
    to[property] = from[property];
  }

  return to;
}
var bak1 = {};
var bak2 = {};
extend1(bak1, { 
    a:1,
    get getter(){ return this.a }, 
    set setter(a) {console.log("a"+a)}
});
extend2(bak2, { 
    a:1,
    get getter(){ return this.a }, 
    set setter(a) {console.log("a"+a)}
});
console.dir(bak1);
console.dir(bak2);

extend1,extend2分别为两个对象copy的方法,而extend2无法copy存储器定义的属性(只能copy到它的值),所以我们要采用extend1来copy对象,结果如下:

六、对象的冻结

对象的冻结有三种方法:

  1. Object.preventExtensions(obj)    //该方法冻结后,对象无法添加新属性
    1. Object.isExtensible(obj)    //该方法用来检验对象是否采用上诉方法冻结
  2. Object.seal(obj)    //该方法冻结后,对象无法添加新属性,无法删除旧属性(实质是把对象的configurable设为false)
    1. Object.isSealed(obj)    //检查该对象是否采用上诉方法冻结
  3. Object.freeze(obj)    //无法添加新属性、无法删除旧属性、也无法改变属性的值,使得这个对象实际上变成了常量
    1. Object.isFrozen(obj)    //检查该对象是否采用上诉方法冻结

局限性:可以通过改变原型改变对象(可以把原型也冻住),如果该对象是数组,只是冻结了数组,没有冻结数组的内容。

 六、数组

你想在JS中形成栈结构吗?很简单,数组+push()+pop()可以实现

var array = [];
array.push('a');
array.push('b');
array.pop(); 
//a

队列:数组+push()+shift()

七、this对象

一谈起this,我们都知道是再说当前对象。但是当前对象又总是显得那么抽象,所以理解起来也显得有些无力了。

那么this到底是什么东西,我觉得可以理解为当前(runtime)的一个环境,举例如下:

var a=1;
var f = function(){
  console.log(this.a);
}
var obj = {
  a:2,
  f:f          
};
f();    //1
obj.f();    //2

先说直接调用f(),因为对于f来讲,f在全局环境执行;而对于obj.f()来讲,obj.f的执行是在obj对象的内部环境,所以导致了结果的不同。

八、call, apply, bind

JS提供了call, apply, bind来切换this的指向。

call不传入参数或传入undifined,null。则默认传入全局值(window)。

var n = 123;
var obj = { n: 456 };

function a() {
  console.log(this.n);
}

a.call() // 123
a.call(null) // 123
a.call(undefined) // 123
a.call(window) // 123
a.call(obj) // 456
func.call(thisValue, arg1, arg2, ...):在thisValue的上下文环境中调用func, arg1, arg2...是func所需参数
call常见套路:
var obj = {};
Object.prototype.hasOwnProperty.call(obj, 'toString') // false

hasOwnProperty方法的原始定义放到obj对象上执行,这样无论obj上有没有同名方法,都不会影响结果。

 

apply与call相似,不过func.apply(thisValue, [arg1, arg2, ...])的参数是一个数组。

 

bind方法用于将函数体内的this绑定到一个对象上。因为bind方法每次会返回一个新方法,如果没有变量名来接收它,则会产生一个匿名函数,这样就会出现一些奇怪的问题

e.g.:如果通过element.addEventListener("click",o.m.bind(o));来添加click监听则会出现remove不了监听的情况发生。

九、JS的模块封装

可以利用JS的立即执行函数起着封装模块的作用,代码如下:

(function($, window, document) {

  function go(num) {
  }

  function handleEvents() {
  }

  function initialize() {
  }

  function dieCarouselDie() {
  }

  //attach to the global scope
  window.finalCarousel = {
    init : initialize,
    destroy : dieCarouselDie
  }

})( jQuery, window, document );

通过finalCarousel对象将init,destory暴露出来,其余内部方法无法访问。

十、proxy

proxy用于修改某些操作的默认行为,在语言层面上作出修改。可以理解成,在目标之前设立了“拦截”,外界对该对象的访问都必须先通过这层拦截。

var object = { proxy: new Proxy(target, handler) };

 如果handler上没有设置任何拦截,等同于直接通向原对象。

 

posted on 2018-09-04 23:26  popcorn丫  阅读(502)  评论(0编辑  收藏  举报