Git Product home page Git Product logo

aqours's Introduction

Aqours

aqours's People

Contributors

aqours avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar  avatar

aqours's Issues

Null and Undefined in JavaScript

We say variables contain values. This is an important distinction to make. Variables aren't the values themselves; they are containers for values. You can think of them being like little cardboard boxes that you can store things in.

Don't confuse a variable that exists but has no value defined with a variable that doesn't exist at all — they are very different things. In the box analogy you saw above, not existing would mean there's no box (variable) for a value to go in. No value defined would mean that there IS a box, but it has no value inside it.

https://developer.mozilla.org/en-US/docs/Learn/JavaScript/First_steps/Variables

Exception: !!document.all === false

When the non-standard property document.all is used as an argument for this constructor, the result is a Boolean object with the value false. This property is legacy and non-standard and should not be used.

- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean

console.log(document.all); // ouput: HTMLAllCollection
console.log(new Boolean(document.all).valueOf() === false); // output: true
console.log(!!document.all === false); // output: true
console.log(typeof document.all === 'undefined'); // output: true

Pseudo-property(getter/setter) in prototype/plain object

It is not possible to simultaneously have a getter bound to a property and have that property actually hold a value, although it is possible to use a getter and a setter in conjunction to create a type of pseudo-property.

- https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get

首先看下伪属性在普通对象中的表现:

const obj = {
    get prop() { return 10 }
};

console.log(obj.prop); // output: 10

obj.prop = 'string';
console.log(obj.prop); // output: 10
console.log(Object.getOwnPropertyDescriptor(obj, 'prop')); // output: Object

delete obj.prop;
obj.prop = 'string';
console.log(obj.prop); // output: string

其次看下伪属性在原型对象中的表现:

class A {
    get a() { return 10 }
}

const instance = new A;

console.log(instance.a); // output: 10

instance.a = 'string';
console.log(instance.a); // output: 10
console.log(
    Object.getOwnPropertyDescriptor(instance, 'a')
); // output: undefined
console.log(
    Object.getOwnPropertyDescriptor(
        Object.getPrototypeOf(instance), 'a'),
); // output: Object

Object.defineProperty(instance, 'a', { value: 'string' });
console.log(instance.a); // output: string
console.log(Object.getOwnPropertyDescriptor(instance, 'a')); // output: Object

Error: WrongDocumentError

这个错误通常是在当前文档(Document)插入其他文档的节点(Node)会产生的错误,常见于IE。

通常来说不同的文档间的节点不能相互插入,通常需要导入节点再插入到文档中,现代浏览器智能化了这个过程,导入操作由浏览器自身完成了。但并不是所有浏览器都是这么做的,因此先导入后插入是更为稳妥的做法。

var body = document.body; // current context
var htmlString = '<div><span>123</span></div>';
var doc = new DOMParser().parseFromString(htmlString, 'text/html'); // other context

console.log(body.ownerDocument === doc); // false

// Mordern Browser (Not Recommend)
// body.appendChild(doc.body.firstChild);

var otherContextNode = doc.body.firstChild;
var currentContextNode = document.importNode(otherContextNode, true);
body.appendChild(currentContextNode);

Overview: architecture of prototype

前言

  1. 本文使用 __proto__ 来表示原型对象,这等同于 ECMAScript 2015 中的 Object.getPrototypeOf(obj)
  2. 本文默认条件表达式返回值为 true,比如:1 === 11 !== 2
  3. 继承常用于表示静态语言中子父类的关系,在 JavaScript 中,我们用继承来表示原型链的依赖关系。

理解三个概念

  1. 原型对象(prototype object)
    JavaScript 中每个对象拥有一个原型对象,对象以其原型对象为模板、从原型对象继承方法和属性。比如:[1, 3] 的原型是 [1, 3].__proto__ 原型对象。

  2. 原型链(prototype chain)
    原型对象也可能拥有原型对象,并从中继承方法和属性,一层一层、以此类推,这种关系常被称为原型链。

  3. 原型属性(prototype property)
    指构造函数的 prototype 属性。原型属性一定是某个对象的原型对象,反过来则不成立。

原型链的架构图

javascript

分析架构

在上述的架构图中,我们把构造函数和构造函数的 prototype 属性分开,这样便于理解同时也简化图形结构。构造函数和构造函数的 prototype 属性分别拥有自己的原型对象。

构造函数的 prototype 属性的原型关系

Object.prototype and null

每个对象均继承自 Object.prototype,因此 Object.prototype 在原型链的顶层。Object.prototype 的原型对象为 null (Object.prototype.__proto__ === null),其既没有属性也没有方法,因此在继承中可以被忽略。

Array.prototype

console.log(Array.prototype.__proto__ === Object.prototype); // output: true

我们可以看出 Array.prototype 的原型对象是 Object.prototype。根据原型链的查找规则,我们可以在 Array.prototype 对象上调用到 Object.prototype 对象上的方法,比如:

console.log(Array.prototype.hasOwnProperty('hasOwnProperty') === false); // output: true

少为人知的一个小知识:Array.prototype 是对象同时也是数组。

console.log(Array.isArray(Array.prototype)); // output: true

Function.prototype

console.log(Function.prototype.__proto__ === Object.prototype); // output: true

和 Array.prototype 如出一辙,不再累述。有一点比较特殊,Function.prototype 同时也是普通函数,并且其没有 prototype 属性。

console.log(typeof Function.prototype === 'function');  // output: true
console.log(Function.prototype.prototype);              // output: undefined

// Uncaught TypeError: Function.prototype is not a constructor
new Function.prototype;

构造函数的原型关系

console.log(Array.__proto__ === Function.__proto__);    // output: true
console.log(Object.__proto__ === Function.__proto__);   // output: true
console.log(Function.prototype === Function.__proto__); // output: true

通过前两行代码可见 ArrayObjectFunction 构造函数的原型是同一个原型对象,而第三行代码则表明这个原型对象就是 Function.prototype。你可能对此有所疑惑,继续往下阅读寻找你要的答案吧。

ECMAScript 2015 的派生构造函数

class CustomArray extends Array { }
console.log(CustomArray.hasOwnProperty('isArray'));     // output: false
console.log(typeof CustomArray.isArray === 'function'); // output: true

这在 ECMAScript 5.1 的继承中很少见,常见的作法是把 isArray 这个属性直接拷贝到 CustomArray 上。我们通过下面的代码来实现 ECMAScript 2015 中的派生构造函数。注意,下面这段代码可能会有性能问题,请不要在生产环境中贸然使用。

function CustomArray() {
    var arr = Array.apply(null, arguments);
    arr.__proto__ = CustomArray.prototype;
    return arr;
}
CustomArray.__proto__ = Array;
CustomArray.prototype = Object.create(Array.prototype, {
    constructor: { enumerable: false, value: CustomArray }
});

console.log(CustomArray.hasOwnProperty('isArray'));     // output: false
console.log(typeof CustomArray.isArray === 'function'); // output: true

那么实现 Function.prototype === Function.__proto__ 这个功能也是一样的。

function customFunction() { }
customFunction.__proto__ = customFunction.prototype;
console.log(customFunction.__proto__ === customFunction.prototype); // output: true

理解了原型链的架构图后,你是否能够明白这些示例中输出的结果了呢?

console.log(null instanceof Object);                    // output: false
console.log(Object.create(null) instanceof Object);     // output: false

console.log(Object.prototype instanceof Object);        // output: false
console.log(Array.prototype instanceof Object);         // output: true
console.log(Function.prototype instanceof Object);      // output: true

console.log(Math instanceof Object);                    // output: true
console.log(Array instanceof Object);                   // output: true
console.log(Function instanceof Object);                // output: true
console.log(Object instanceof Object);                  // output: true

console.log(Array instanceof Function);                 // output: true
console.log(Function instanceof Function);              // output: true
console.log(Object instanceof Function);                // output: true

console.log(Array.prototype instanceof Function);       // output: false
console.log(Function.prototype instanceof Function);    // output: false
console.log(Object.prototype instanceof Function);      // output: false

console.log(Array instanceof Array);                    // output: false

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.