Javascript 基础

1、函数防抖和函数节流

【《javascript高级程序设计》里,函数节流是这里讲的函数防抖。】
函数防抖: 在事件被触发n秒后再执行回调,如果在这n秒内又被触发,则重新计时。
典型的例子:用户输入验证用户名是否有效。假如用户不再输入了,2秒后就验证用户名是否有效,而如果还没到2秒,就重新开始计算2秒。

/**
 * 函数防抖方法
 * @param Function fn 延时调用函数
 * @param Number interval 间隔多长时间
 */
let debounce = function(fn, delay){
    let timer = null
    return function() {
        clearTimeout(timer)
        timer = setTimeout(() => {
            fn()
        }, delay)
    }
}

函数节流:规定一个单位时间,在这个单位时间内,只能有一次触发事件的回调函数执行,如果在同一个单位时间内某事件被触发多次,只有一次能生效。

function throttle(fn, interval) {
    let prev = 0
    return function(){
        let now = + new Date()
        if(now - prev > interval){
            fn()
            prev = now
        }
    }
}
2、js判断数据类型
  • typeof
    可以判断 undefined、string、number、Boolean、function。
    但不能判断 null, typeof null 返回 Object
    也不能判断 Array,typeof 数组 返回 Object
  • instanceof
    用于测试构造函数的 prototype 属性是否出现在对象的原型链中。
    可以用它判断 Function、Array。
    但不要用它判断 Object,因为 数组/函数 instanceof Object 为 true。
  • constructor
    目前运算最快的判断变量类型的方式。
    可以判断除了 nullundefined 类型。
    当检测 nullundefined 类型的 constructor 属性时会报错。
  • Object.prototype.toString.call()
Object.prototype.toString.call(null);  //  "[object Null]"
Object.prototype.toString.call(undefined);  //  "[object Undefined]"
Object.prototype.toString.call(false);  //  "[object Boolean]"
Object.prototype.toString.call(123);  //  "[object Number]"
Object.prototype.toString.call('abc');  //  "[object String]"
Object.prototype.toString.call([]);  //  "[object Array]"
Object.prototype.toString.call({});  //  "[object Object]"
Object.prototype.toString.call(function(){});   //  "[object Function]"

PS:在ES5中的判断数组还可以用Array.isArray()。

3、null 和 undefined 的区别

阮一峰的:

  • null 在其他语言中与对象有关,typeof null 返回 Object
    undefined 是后来设计的。
  • 在JS最初设计的时候,
    null 是一个表示"无"的对象,转为数值时为0,例如:Number(null)0
    undefined 是一个表示"无"的原始值,转为数值时为NaN。Number(undefined)NaN
  • 后来,修改为:
    null 表示"没有对象",即该处不应该有值。例如:null 作为对象原型链的终点。
    undefined 表示"缺少值",就是此处应该有一个值,但是还没有定义。

网上的:

  • undefined 希望表示一个变量最原始的状态,而非人为操作的结果 。
    typeof 之所以会判定 null 为 Object 类型,是因为JavaScript 数据类型在底层都是以二进制的形式表示的,二进制的前三位为 0 会被 typeof 判断为对象类型,而 null 的二进制位恰好都是 0 ,因此,null 被误判断为 Object 类型。
  • null 希望表示 一个对象被人为的重置为空对象。
    当一个对象被赋值了null 以后,原来的对象在内存中就处于游离状态,GC 会择机回收该对象并释放内存。因此,如果需要释放某个对象,就将变量设置为 null,即表示该对象已经被清空,目前无效状态。

补充:

  • 《重学前端》:undefined 可以作为一个变量来用,程序不会报错,但是如果想把 null 作为变量用程序会报错。所以,通常我们写一些代码防止undefined被污染。
  • JS类型值是存在 32 BIT 单元里,32位有1-3位表示 TYPE TAG,其它位表示真实值,而表示 Object 的标记位正好是低三位都是0。
  • 曾经有提案 typeof null === 'null',但提案被拒绝。

4、拷贝对象(浅拷贝,深拷贝)
  • Object.assign()
  • es6中的对象展开运算符
  • for in
    缺点:
    1. 属性描述符不能被复制。
      Object.defineProperty() 中定义的描述符不会被拷贝,新对象通过 Object.getOwnPropertyDescriptor() 获取到的值为 undefined
    2. 只能拷贝可枚举属性。
      通过 Object.defineProperty() 定义了 enumerablefalse的属性不会被拷贝。
    3. 若属性的某个值为对象,原对象和拷贝后对象的该属性共享这个对象。
  • JSON.parse(JSON.stringify())
    缺点:
  • 不能拷贝值为函数、正则等的属性。
  • 若对象有循环引用,会报错。

数组的深拷贝:
(这里待补充……)

5、闭包

参考资料:方应杭的知乎文章

什么是闭包?
MDN:闭包是函数和声明该函数的词法环境的组合。
winter:闭包是绑定了执行环境的函数。它与普通函数的区别是,它携带了执行环境。闭包包含2个部分:
1、环境部分
环境:函数的词法环境(执行上下文的一部分)。
标识符列表:函数中用到的未声明的变量。
2、表达式部分

闭包有什么好处?
闭包常常用来「间接访问一个变量」。换句话说,「隐藏一个变量」。

项目中用过闭包?
有时候写组件的时候,组件里面的内容不想要被外部访问到,就需要创建一个封闭的环境,不能让别人「直接访问」这个变量。那怎么办呢?用局部变量。但是用局部变量别人又访问不到,怎么办呢?暴露一个访问器(函数),让别人可以「间接访问」。
比如写签约支付组件:

// 组件
(function(){
  var XYS = window.XYS = window.XYS || {}
  XYS.Payment = function(options){
    // 这里是支付组件的内容
  }
})()

// 组件调用
XYS.Payment({})

闭包什么情况下会造成内存泄漏?
闭包不会造成内存泄漏,说内存泄漏是因为 IE 有 bug,IE 在我们使用完闭包之后,依然回收不了闭包里面引用的变量。

6、原型链和继承

参考资料1:JS高级程序设计

理解函数:

函数是对象,函数名是指针。函数名仅仅是指向函数的指针,因此函数名与包含对象指针的其他变量没有什么不同。

ECMAScript 只支持实现继承,而且其实现继承主要是依靠原型链来实现的。

构造函数、原型和实例的关系:

构造函数都有一个原型对象,原型对象都包含一个指向构造函数的指针,而实例都包含一个指向原型对象的内部指针。

可以这么理解:
每个函数被创建出来后,它都会有一个prototype属性(即原型),这个属性是一个对象,这个对象包含一个指向该构造函数的指针。而实例都有一个指向这个属性对象的内部指针。

敲重点:构造函数是一个对象,函数的prototype属性也是一个对象,prototype属性有一个指针指向构造函数。

假如我们让原型对象等于另一个类型的实例,此时的原型对象将包含一个指向另一个原型的指针,相应地,另一个原型中也包含着一个指向另一个构造函数的指针。假如另一个原型又是另一个类型的实例,那么上述关系依然成立,如此层层递进,就构成了实例与原型的链条。这就是所谓的原型链。

下图中,有5个对象,分别是:superType、superType.prototype、subType、subType.prototype、instance。(你不用去理会这5个对象是实例还是构造函数,也不管是构造函数对象还是字面量对象,总之它们5个都是对象)。

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

分析:
实例 instance__proto__ 属性是一个指针,指向 SubType.prototype 这个对象。
构造函数SubTypeprototype属性是一个指针,指向 SubType.prototype 这个对象。
SubType.prototype这个对象是 SuperType 的一个实例,所以它也有__proto__属性,指向 SuperType.prototype这个对象。
构造函数SuperTypeprototype属性是一个指针,指向 SuperType.prototype 这个对象。

实例以及构造函数和原型之间的关系

如何确定原型和实例的关系?

  • instanceof 操作符:instance instanceof parentType
  • isPrototypeOf(): parentType.isPrototypeOf(instance)

原型链的问题:
1、包含引用类型值的原型属性会被所有实例共享。

function Parent(){
  this.number = [1,2,3]
}
function Children(){}
Children.prototype = new Parent()

var c1 = new Children()
var c2 = new Children()
console.log(c1.number === c2.number)  // true

2、在创建子类型的实例时,不能向父类型的构造函数中传递参数。

参考资料2:简书的某篇文章

原型是一个对象。每个函数都有一个属性叫做原型,这个属性指向一个对象。
原型是函数对象的属性,并不是所有对象的属性,对象经过构造函数new出来,那么这个new出来的对象,它的构造函数有一个属性叫原型。

每次你定义一个函数的时候,这个函数的原型属性也就被定义出来了,也就可以使用了,如果不对它进行显示赋值的话,那么它的初始值就是一个空的Object对象。

记住:原型只是函数的一个属性!

function Fn(){}
console.log(Fn.prototype)
打印结果

所有函数的构造函数都是Function。

function Fn(){}
console.log(Fn.constructor)  // ƒ Function() { [native code] }
继承

借用构造函数(经典继承 / 伪造对象)
优点:
1、子类型构造函数中向超类型构造函数传递参数。
2、包含引用类型值的原型属性是独立的,不会被所有实例共享。

function SuperType(name){
  this.name = name;
  this.colors = ["red", "blue", "green"];
}
function SubType(){
  //继承了 SuperType
  SuperType.call(this, 'Yumi');
}
var instance1 = new SubType();
instance1.colors.push("black");
alert(instance1.colors);    //"red,blue,green,black"
var instance2 = new SubType();
alert(instance2.colors);    //"red,blue,green"

ES6里的extends是哪种继承方式?

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342