JavaScript 的一些概念

0、一些概念

(1)JavaScript 中的所有事物都是对象:字符串、数值、数组、函数;此外,JavaScript 允许自定义对象。对象只是一种特殊的数据,对象拥有属性和方法;即对象只是带有属性和方法的特殊数据类型。

  • 布尔型可以是一个对象。数字型可以是一个对象。字符串也可以是一个对象。日期是一个对象。数学和正则表达式也是对象。数组是一个对象。甚至函数也可以是对象。
  • 请不要把字符串、数值和布尔值声明为对象!如果通过关键词 “new” 来声明 JavaScript 变量,则该变量会被创建为对象:
    var x = new String(); // 把 x 声明为 String 对象
    var y = new Number(); // 把 y 声明为 Number 对象
    var z = new Boolean(); // 把 z 声明为 Boolean 对象
    请避免字符串、数值或逻辑对象,他们会增加代码的复杂性并降低执行速度。

(2)JavaScript 是面向对象的语言,但 JavaScript 不使用类。在 JavaScript 中,不会创建类,也不会通过类来创建对象(就像在其他面向对象的语言中那样)。JavaScript 基于 prototype(原型),而不是基于类的。(函数 + prototype 机制)

  • 基于类的是创建模型,基于原型的是经验模型,前者是现有马这个概念,才有胯下之马这个实体,后者是先有胯下之马这个实体,才有马这个概念。
  • 在思考面向原型的时候,类的概念有是可以的,因为本质上对象的原型就是类。但是,类构造出对象的这个过程却要不得,面向原型里,是由具体对象推导出原型来的。
  • 访问对象的属性或者方法时,会访问其__proto__以及__proto__的__proto__,直到找到这个属性或者方法为止,而函数的prototype属性执行后会返回执行结果的__proto__。
1、apply() 方法与 call() 方法

apply() 方法能劫持另外一个对象的方法,继承另外一个对象的属性。

var person = {
    fullName: function (city, country) {
        return this.firstName + " " + this.lastName + "," + city + "," + country;
    }
}
var person1 = {
    firstName: "Bill",
    lastName: "Gates"
}
var x = person.fullName.apply(person1, ["Seatle", "USA"]);
// var x = person.fullName.call(person1, "Seatle", "USA");
// 应用输出:
Bill Gates, Seatle, USA
2、函数节流(throttle)与函数防抖(debounce)

函数节流:限制一个函数在一定时间内只能执行一次;即在一定时间之内,限制一个动作只执行一次。

// 时间戳方案
function throttle(fn, wait) {
    let pre = Date.now();
    return function () {
        let context = this;
        let args = arguments;
        let now = Date.now();
        if (now - pre >= wait) {
            fn.apply(context, args);// args 即上面的 pre,this 是为了能持有 args 
            pre = Date.now();
        }
    }
}

window.addEventListener("mousemove", throttle(fu, 1000));

函数防抖:短时间内多次触发同一事件,只执行最后一次,或者只执行最开始的一次,中间的不执行。

/**
   * @desc 函数防抖
   * @param func 目标函数
   * @param wait 延迟执行毫秒数
   * @param immediate true - 立即执行, false - 延迟执行
   */
function debounce(func, wait, immediate) {
    let timer;
    return function () {
        let context = this;
        let args = arguments;

        if (timer) clearTimeout(timer);
        if (immediate) {
            let callNow = !timer;
            timer = setTimeout(() => {
                timer = null;
            }, wait);
            if (callNow) func.apply(context, args);
        } else {
            timer = setTimeout(() => {
                func.apply(context, args);
            }, wait)
        }
    }
}
3、数组去重的n种方式

利用数组 filter 方法过滤:

Array.prototype.unique = function unique() {
    var res = this.filter(function (item, index, array) {
        return array.indexOf(item) === index;
    });
    return res;
}

利用对象属性的唯一性:

Array.prototype.unique = function () {
    var temp = [], hash = {};    // hash 作为哈希表
    for (var i = 0; i < this.length; i++) {
        if (!hash[this[i]]) {    // 如果哈希表中没有当前项
            hash[this[i]] = true;
            temp.push(this[i])
        }
    }
    return temp;
}

利用 ES6 set 数据结构:

Array.prototype.unique = function () {
    return Array.from(new Set(this));
}

运行速度差异不大,不过鉴于 set 是 ES6 新加内容,在实际开发环境中,推荐使用稳定性和速度都比较不错的前两个方法。

4、解构赋值【ECMAScript 6.0 规范(ES6)】
1、使用数组成员对变量赋值时,优先使用解构赋值:
const arr = [1, 2, 3, 4];
// bad
const first = arr[0];
const second = arr[1];
// good
const [first, second] = arr;
2、函数的参数如果是对象的成员,优先使用解构赋值:
// bad
function getFullName(user) {
  const firstName = user.firstName;
  const lastName = user.lastName;
}
// good
function getFullName(obj) {
  const { firstName, lastName } = obj;
}
// best
function getFullName({ firstName, lastName }) {
}
3TODO: 如果函数返回多个值,优先使用对象的解构赋值,而不是数组的解构赋值。这样便于以后添加返回值,以及更改返回值的顺序:
// bad
function processInput(input) {
  return [left, right, top, bottom];
}
// good
function processInput(input) {
  return { left, right, top, bottom };
}
const { left, right } = processInput(input);
for (const { name, age } of persons) {
  console.log(name);
  console.log(age);
}
5、get 和 set 方法

getter 是获取属性值,setter 是设置属性值,getter 不带任何参数,setter 设置键值,值以参数的形式传递,在 setter 函数体中,一切的 return 都是无效的,当只有 setter 函数时,那这个属性是只写的,当只有 getter 函数时,那这个属性是只读的,同时有 setter、getter 函数,这个属性可读可写。

let o = {
    get x() {
        return 7;
    },
    set x(val) {
        console.info("不能设置x的值");
    }
}
o.x    //7 读取x值的时候,会使用get方法
o.x = 9  //不能设置x的值 赋值x时,会使用set方法
let p = {
    get() {
        return this._p;
    },
    set(value) {
        value = value === undefined ? 0 : value;
        this._p = value;
        // 悄悄干点其它的操作
        this.xxxxx(value);
    }
}

参考:
苏格拉没有底:https://segmentfault.com/u/sugelameiyoudi_5a3a4031b8a3f/articles

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值