开发者社区> java小萌新> 正文
阿里云
为了无法计算的价值
打开APP
阿里云APP内打开

js基础

简介: demo
+关注继续查看

Objects中的属性:

  • 1: Object.keys 和 Object.getOwnPropertyNames: 检索对象中所有的属性名,前一个方法返回所有可枚举的属性名,后一个方法不考虑属性的可枚举性一律返回, 但都不支持Symbol属性,ES6中增加 Object.getOwnPropertySymbols()方法来检索对象中的Symbol属性
  • 2:
//obj instanceof Array == Array[Symbol.hasInstance](obj)

function specailNumber(){}
Object.defineProperty(specailNumber,Symbol.hasInstance,{value:(v)=>(v instanceof Number) && (v >= 1 && v <= 100)})
var two = new Number(2)
    zero = new Number(0)
print(two instanceof specailNumber)
print(zero  instanceof specailNumber)
-------------------------------------------------------------------
let collection = {
    0:"hello",
    1:"world",
    length:2,
    [Symbol.isConcatSpreadable]:true
};
let message = ["HI"].concat(collection);
print(message) //[ 'HI', 'hello', 'world' ]

0 ES5 有5种类型, ES6有6种类型

  • 1: ES5: 字符串型,数字型,布尔型,null,undefined
  • 2 : ES6 + Symbol ,Symbol是原始值,因此调用new Symbol() 会报错. 但是可以 typeof symbol
  • 3: Symbol的描述被存储在内部的[[Description]]属性中,只有当调用Symbol的toString()方法时才可以读这个属性
  • 4: 所有使用可计算属性名的地方,都可以使用Symbol.Object.defineProperty()方法和Object.defineProperties()方法
  • 5: Symbol.for("uid"), 首先在全局Symbol注册表中搜索键为"uid"的Symbol是否存在,存在返回,不存在,创建新的Symbol并返回
let firstname = Symbol("firstname");
//可计算
let person = {
    [firstname]:"Nichols"
};
//将属性设置为只读
Object.defineProperty(person,firstname,{writable:false});
let lastname = Symbol("last name");
Object.defineProperties(person,{
    [lastname]:{
        value:"Zakes",
        writable:false
    }
});
print(person.firstname,person.lastname);

1 箭头函数

  • 1: 没有this,super,arguments和new.target绑定,箭头函数中的 this,super,arguments和new.target这些值由外围最近一层非箭头函数决定,
  • 2: 不能通过new关键字调用, 箭头函数没有[[]Construct]方法,所以不能作为构造函数,如果用了new就会抛出错误.
  • 3: 没有原型,由于不能通过new构造,因而没有构造原型的需求,所以箭头函数不存在prototype这个属性
  • 4: 不可以改变this的绑定,函数内部的this值不可以改变,在函数的生命周期内始终保持一致.
  • 5: 不支持 arguments对象,箭头函数没有arguments绑定,所以你必须通过明明函数和不定参数这两种形式访问函数的参数.
  • 6: 不支持重复的命名参数 无论严格参数还是非严格模式下,箭头函数都不支持重复的命名参数
  • 7: 箭头函数同样也有一个name属性,这与其他函数相同.
  • 8: 箭头函数的设计初衷是: 即用即弃, 箭头函数内的this也不能通过call apply bind来改变.但是可以在箭头函数上调用call apply bind方法,与其他函数不同,箭头函数的this值不会受这些方法的影响
var sum = (num1,num2) => num1+num2;
print(sum.call(null,1,2))
print(sum.apply(null,[1,2]))
var boundSum = sum.bind(null,1,2)
print(boundSum())

2 ES6中尾递归优化: 满足以下条件,尾调用不再创建新的栈帧,而是清除并重用当前栈帧

  • 1: 尾调用不访问当前栈帧的变量(也就是说函数不是一个闭包)
  • 2: 在函数内部,尾调用是最后一条语句
  • 3: 尾调用的结果作为函数值返回

3: js中的对象 普通对象 特异对象 标准对象 内建对象

  • 1: 普通对象(ordinary): 具有js对象所有的默认内部行为
  • 2: 特异对象(exotic) 具有某些与默认行为不符的内部行为
  • 3: 标准对象: ES6规范中定义的对象.Array Date等
  • 4: 内建对象: 脚本开始执行时存在于js执行环境中的对象,所有标准对象都是内建对象.

4: Object.assign and 自有属性的枚举顺序

  • 1: 所有数字按升序排序
  • 2: 所有字符串键按照他们被加入对象的顺序排序
  • 3: 所有symbol键按照他们被加入对象的顺序排序
var obj = {
    a:1,
    0:1,
    c:1,
    2:1,
    b:1,
    1:1
};
obj.d = 1;
print(Object.getOwnPropertyNames(obj).join("")) //012acbd

5: 改变对象的原型 Object.setPrototypeof()

let person = {
    getGreeting(){
        return "hello";
    }
}
let dog = {
    getGreeting(){
        return "woof!";
    }
}
//person prototype
let friend = Object.create(person);
print(friend.getGreeting()); //hello
print(Object.getPrototypeOf(friend) == person); //true
//set prototypeOf dog
Object.setPrototypeOf(friend,dog);
print(friend.getGreeting()) //woof!
print(Object.getPrototypeOf(friend) == dog); //true

6: 简化原型访问的super引用,必须在简写方法的对象中使用Super引用

let person = {
    getGreeting(){
        return "hello";
    }
}
let dog = {
    getGreeting(){
        return "woof!";
    }
}
let friend = {
    getGreeting(){
        //return Object.getPrototypeOf(this).getGreeting.call(this) +" hi!";
        return super.getGreeting() +" hi!";
    }
}

Object.setPrototypeOf(friend,person);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) === person)

Object.setPrototypeOf(friend,dog);
print(friend.getGreeting())
print(Object.getPrototypeOf(friend) == dog)

7: 使用var let const解构声明变量,则必须提供初始化程序.

  • 1: 如果不使用解构功能,则var let声明不强求提供初始化程序,但是const需要
  • 2: 任何解构表达式尝试读取 null or undefined的属性时都是报错.
  • 3: 读取type的属性并将其存储在变量localType中,let {type:localType,name:localName} = node
  • 4: 可以嵌套读取
let node = {
    type:"Identity",
    name:"foo",
    loc:{
        start:{
            line:1,
            column:1
        },
        end:{
            line:2,
            column:2
        }
    }
}
let {loc :{end}} = node ;
print(end.line,end.column)
let a = 1,
    b = 2 ;
[a,b] = [b,a]
print(a,b) //交换 a,b的值

// 复制数组
let colors = ["red","green","blue"];
let [...clone] = colors
print(clone)
print(colors.join(" "))
print(colors.concat(" "))

//应用场景1
function setCookie(name,value,{secure,path,domain,expire} = {}) //使用解构的话比较清晰

// ES6 之前的模拟 set and map 
var set = Object.create(null);
set.foo = true 
if(set.foo){
    print("hello")
}
var map = Object.create(null)
map.foo = "bar";
print(map.foo)

// 若引用set, 集合中的弱引用如果是对象的唯一引用,则会被回收并且释放相应内存(不支持原始值,只支持引用类型)

let set = new WeakSet(),
    key = {};
set.add(key);
print(set.has(key)); //true
set.delete(key);
print(set.has(key)); //false
//注意weakset: 不可迭代即不可以使用for..in (2)不能不报露任何迭代器例如keys and values (3)不支持forEach (4) 不支持size属性

// set and map底层都是Object.is判断相等的
 let map = new Map();
map.set("title","Understanding js");
map.set("year",2016)
print(map.get("year"))
print(map.get("title"))
//默认初始化
let map = new Map([["title","Understanding js"],["year",2016]]);
//迭代map (value,key,ownermap) => print ... 
map.forEach((v,k) => print(k+" -> "+v))
//使用weak map 存储私有数据
let Person = (function(){
    let privateDate = new WeakMap();
    function Person(name){
        privateDate.set(this,{name:name});
    }
    Person.prototype.getName = function(){
        return privateDate.get(this).name;
    };
    return Person;
}());
var p1 = new Person("shen");
var p2 = new Person("yang");
print(p1.getName())
print(p2.getName())

//新的迭代器: for ..of 循环,展开运算符(...) ,异步编程也可以使用迭代器

//ES5中写迭代器的写法, ES6中增加了 一个生成器对象,他可以让创建迭代器对象变得简单
function createIter(items){
    var i = 0;
    return {
        next : function(){
            var done = (i>=items.length);
            var value = !done ? items[i++] : undefined;
            return {done:done,value:value};
        }
    }
}
var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())

//生成器是一种返回迭代器的函数,通过function*来表示,函数中会用到新的关键字yield
function*createIter(){
    yield 1;
    yield 2;
    yield 3;
}
function*createIter(items){
    for(let i = 0;i<items.length;i++){
        yield items[i];
    }
}

var iter = createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//生成器对象的方法,
let o = {
    *createIter(items){
        for(let i =0;i<items.length;i++){
            yield items[i];
        }
    }
}
let iter = o.createIter([1,2,3])
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())

//由于生成器默认会为Symbol.iterator属性赋值,因此所有通过生成器创建的迭代器都是可迭代对象
//for-of 循环每执行一次都会调用可迭代对象的next方法
//访问默认迭代器
let values = [1,2,3]
let iter = values[Symbol.iterator]();
print(iter.next())
print(iter.next())
print(iter.next())
print(iter.next())
//检测对象是否可迭代

//默认开发者定义的对象都是不可迭代对象,但如果给Symbol.iterator属性添加一个生成器,者可以变成一个迭代对象
let collection = {
    items:[],
    *[Symbol.iterator](){
        for(let item of this.items){
            yield item;
        }
    }
}
collection.items.push(1);
collection.items.push(2);
collection.items.push(3);

for(let x of collection){
    print(x)
}

// 内建迭代器: entries() values() keys()
let data = new Map([["title","understanding ES6"],["format","ebook"]]);
for(let [key,value] of data){
    print(key+" -> "+value);
}

//第二次调用next()方法传入的值为4,他会被赋值给变量first,函数继续执行
function *createIter(){
    let first = yield 1;
    let second = yield first + 2;
    yield second + 3;
}
let iter = createIter();
print(iter.next());
print(iter.next(4));
print(iter.next(5));
print(iter.next());

//yield语句也可以抛出异常
function *createIter(){
    let first = yield 1;
    let second;
    try{
        second = yield first + 2;
    }catch(ex){
        second = 6;
    }
    yield second +3;
}
let iter = createIter();
print(iter.next())   // { value: 1, done: false }
print(iter.next(4)) // { value: 6, done: false }
print(iter.throw(new Error("Boom!")))  //{ value: 9, done: false }
print(iter.next()) //{ value: undefined, done: true }

// yield  遇到 return 也会提前返回

// 在某些情况下,需要两个迭代器合二为一,这时可以创建一个生成器,再给yield语句添加一个星号,就可以将生成数据的过程委托给其他生成器.
function *createNumber(){
    yield 1;
    yield 2;
}
function *createColor(){
    yield "red";
    yield "green";
}
function *createCombinIter(){
    yield *createNumber();
    yield *createColor();
    yield true;
}
var iter = createCombinIter();
print(iter.next()) //{ value: 1, done: false }
print(iter.next()) //{ value: 2, done: false }
print(iter.next())//{ value: 'red', done: false }
print(iter.next())//{ value: 'green', done: false }
print(iter.next())//{ value: true, done: false }
print(iter.next())//{ value: undefined, done: true }

//简单任务执行器: 由于执行yield语句会暂停当前函数的执行过程并等待下一次调用next()方法,因此可以创建一个函数,在函数中调用生成器生成相应的迭代器,从而在不用回调函数的基础上实现异步调用next方法

function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            result = task.next()
            step()
        }
    }
    //开始迭代
    step();
}
run(function*(){
    print("1...");
    yield;
    print("2 ...");
    yield;
    print("3 ... ");
});

//任务执行器之间互相通信
function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            result = task.next(result.value)
            step()
        }
    }
    //开始迭代
    step();
}
run(function*(){
    let value = yield 1;
    print("value: "+value); // 1
    value = yield value + 3 
    print("value: "+value) // 4

//如果result.value是一个函数
function run(taskDef){
    //创建一个无使用限制的迭代器
    let task = taskDef();
    let result = task.next();
    //循环调用next函数
    function step(){
        //如果任务没完成,则继续完成
        if(!result.done){
            if(typeof result.value == "function"){
                result.value(function(err,data){
                    if(err){
                        result = task.throw(err);
                        return;
                    }
                    result = task.next(data);
                    step();
                })
            }else{
                result = task.next(result.value);
                step();
            }
        }
    }
    //开始迭代
    step();
}
let fs = require("fs");
function readFile(filename){
    return function(callback){
        fs.readFile(filename,callback);
    };
}


run(function*(){
   let contents = yield readFile("data.txt");
   print(String(contents));
   print("Done");

});

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
JS基础-完美掌握继承知识点
前言 上篇文章详细解析了原型、原型链的相关知识点,这篇文章讲的是和原型链有密切关联的继承,它是前端基础中很重要的一个知识点,它对于代码复用来说非常有用,本篇将详细解析JS中的各种继承方式和优缺点进行,希望看完本篇文章能够对继承以及相关概念理解的更为透彻。 本篇文章需要先理解原型、原型链以及call 的相关知识: JS基础-函数、对象和原型、原型链的关系 js基础-面试官想知道你有多理解call,apply,bind? 何为继承? 维基百科:继承可以使得子类具有父类别的各种属性和方法,而不需要再次编写相同的代码。 继承是一个类从另一个类获取方法和属性的过程。 PS:或者是多个类 JS实现继承
16 0
玩转JS基础——值和引用
在 JavaScript 中,数据类型整体上来讲可以分为两大类:基本类型和引用数据类型
42 0
玩转JS基础——包装类型
在 ES 中,数据的分类分为基本数据类型和引用类型。
13 0
JS - 基础篇(下)
JS - 基础篇(下)
15 0
Js 基础补充
js参考手册:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript
28 0
js基础之闭包与继承
js基础之闭包与继承
41 0
Node.js基础
NPM 使用介绍 npm可以很方便的下载别人写好的模板,也可以将自己写好的模板发布别人。 win+r打开运行,输入cmd,打开dos命令窗口,然后: 查看npm版本 输入:npm -v npm升级 输入:npm install npm -g npm安装模板 输入:npm install 模板 js文...
1207 0
js部分基础
1.js的基本类型有哪些?引用类型有哪些?null和undefined的区别。   基础类型:number,null,regex,string,boolean   引用类型 : object,function,array   null是数据类型,undefined未定义    2.
922 0
JS基础--问题记录
1. {}var a={};{}是一个空的对象,是 new Object();的简写。2.判断元素是存在 //jQuery 对象中元素的个数。当前匹配的元素个数。 size 将返回相同的值。 if ($("#resultDiv").
602 0
+关注
java小萌新
什么都不懂的小萌新
14
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
低代码开发师(初级)实战教程
立即下载
阿里巴巴DevOps 最佳实践手册
立即下载
冬季实战营第三期:MySQL数据库进阶实战
立即下载