Skip to content
On this page

整理汇总一周看到的文章与学到的知识(2021-12-17 ~ 2021-12-23)

文章

面试官问:JS 的继承

内容

js
// 构造函数
function F() {}
// 实例
var f = new F();

// 每一个函数都有 prototype 属性,只有在 new + 构造函数的时候,prototype 属性才有用,普通的函数调用,不会用到 prototype 属性
// 每一个对象都有 __proto__ 属性,__proto__ 属性指向当前对象的原型对象,js是基于原型来实现继承
// 函数也是对象(数组、正则都是对象)

// 用于方便的找到构造函数
F.prototype.constructor === F; // true

// 这段代码是js能实现继承的关键
F.__proto__ === Function.prototype; // true

// Function 是 Object 的实例(Function 和 Object 都是函数)
Function.prototype.__proto__ === Object.prototype; // true
// Object 的原型是 null(规定)
Object.prototype.__proto__ === null; // true

// f 是 F 的实例,这就代表 f 继承与 F
f.__proto__ === F.prototype; // true
// F 是实例a,Function 是实例b,实例a和b的原型都是 Object.prototype
F.prototype.__proto__ === Object.prototype; // true

以下是一个 es6 的例子

js
// ES6
class Parent {
    constructor(name) {
        this.name = name;
    }
    static sayHello() {
        console.log('hello');
    }
    sayName() {
        console.log('my name is ' + this.name);
        return this.name;
    }
}
class Child extends Parent {
    constructor(name, age) {
        super(name);
        this.age = age;
    }
    sayAge() {
        console.log('my age is ' + this.age);
        return this.age;
    }
}

let parent = new Parent('Parent');
let child = new Child('Child', 18);

console.log('parent: ', parent); // parent:  Parent {name: "Parent"}

Parent.sayHello(); // hello
parent.sayName(); // my name is Parent
console.log('child: ', child); // child:  Child {name: "Child", age: 18}
Child.sayHello(); // hello
child.sayName(); // my name is Child
child.sayAge(); // my age is 18

console.log(Child.prototype.__proto__ === Parent.prototype);
// true

console.log(Child.__proto__ === Parent);
// true

// 1、构造器原型链
Child.__proto__ === Parent; // true
Parent.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
// 2、实例原型链
child.__proto__ === Child.prototype; // true
Child.prototype.__proto__ === Parent.prototype; // true
Parent.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true

// 子类中使用的 super,相当于 es5 中使用的 call apply

Child.__proto__ === Parent 这两个居然相等,不太懂?这是《JavaScript 高级程序设计-第 3 版》 章节 6.3 继承 中的 寄生组合式继承

__proto__ 只是一个方便我们测试的属性,在正式项目中,不要使用它,那么改怎么更改 __proto__ 的值呢?应该使用 newObject.createObject.setPrototypeOf

new

  1. 创建一个对象 a
  2. 对象 a 的 __proto__ 赋值为构造函数的 prototype (在浏览器中[[Prototype]] 就是 __proto__
  3. 调用构造函数,并且使用对象 a 的上下文(这是构造函数没有返回Object的情况,如果构造函数返回了Object,那么对象 a 就赋值为这个返回的对象)

Object.create() es5 提供的:

js
// 简版:也正是应用了new会设置__proto__链接的原理。
if (typeof Object.create !== 'function') {
    Object.create = function (proto) {
        function F() {}
        F.prototype = proto;
        return new F();
    };
}

Object.setPrototypeOf es6 提供的:

js
Object.setPrototypeOf =
    Object.setPrototypeOf ||
    function (obj, proto) {
        obj.__proto__ = proto;
        return obj;
    };

node 的 inherits 就是使用 Object.setPrototypeOf 实现的

util.inherits 用法 以及 源码

还可以看下 babel 编译 es6 之后的代码

思考

例子还是挺深奥的,但感觉没有讲的很简单,看着有点难懂,只是挂了一些书的链接,但这些书还是不错的,可以看下

还是不太懂 prototype 和 __proto__ 的区别?

可以了解一下 node 的其他工具函数是怎么写的,比如 promisify ?

学了近三年前端,原型继承还是不能清晰理解,惭愧呀

张鑫旭:前端工程师应该为用户体验负责

内容

首先提出了一些常见的体验应该引起重视,如按钮要有按下的反馈、图标点击区域要大、忽视边界异常处理,如:低网速、无数据、脚本出错等、语言错误,使用 div 代替按钮,使用 div 代替链接

后面分析总结了引起这些问题的原因,以及解决方案

思考

原因以及解决方案讲的很清晰,需要大量功底,如果让我总结,可能就只是有个模糊的概念,但不能清晰的划分出来

我也有这种感受,因为我虽然是开发人员,但也是用户,作为用户我会经常吐槽这个产品做的真垃圾,用着真难受,但我在开发的时候也确实不想因为用户体验而多写大量代码,感觉这是吃力不讨好,收益不明显,比较同意等的那个观点(但我认为还要等很久),等到大家功能上都差不了太多的时候,就会在用户体验上卷起来了(在用户体验方面,还是很佩服苹果的)

JS 的 6 种打断点的方式,你用过几种?

内容

  1. 普通断点
  2. 加条件的普通断点
  3. DOM 断点(当子元素发生变化时触发)
  4. Url 断点
  5. event listener 断点(如鼠标点击事件)
  6. Node 的 error 断点(只有 vscode 可以)

思考

dom url 和 listener 学到了,但一般在什么情况使用呢?(学到了,并且用了,才是真正的会了)